claude-code-workflow 6.1.4 → 6.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +10 -0
- package/.claude/agents/action-planning-agent.md +857 -778
- package/.claude/agents/cli-execution-agent.md +266 -269
- package/.claude/agents/cli-explore-agent.md +2 -2
- package/.claude/agents/cli-lite-planning-agent.md +142 -92
- package/.claude/agents/cli-planning-agent.md +4 -4
- package/.claude/agents/code-developer.md +7 -6
- package/.claude/agents/conceptual-planning-agent.md +2 -2
- package/.claude/agents/context-search-agent.md +31 -32
- package/.claude/agents/doc-generator.md +4 -4
- package/.claude/agents/memory-bridge.md +93 -93
- package/.claude/agents/test-context-search-agent.md +8 -7
- package/.claude/agents/test-fix-agent.md +7 -6
- package/.claude/commands/clean.md +516 -0
- package/.claude/commands/memory/compact.md +383 -0
- package/.claude/commands/memory/docs-full-cli.md +471 -471
- package/.claude/commands/memory/docs-related-cli.md +386 -386
- package/.claude/commands/memory/docs.md +615 -615
- package/.claude/commands/memory/load.md +5 -5
- package/.claude/commands/memory/tech-research-rules.md +310 -0
- package/.claude/commands/memory/update-full.md +332 -332
- package/.claude/commands/memory/workflow-skill-memory.md +4 -4
- package/.claude/commands/task/create.md +151 -151
- package/.claude/commands/version.md +254 -254
- package/.claude/commands/workflow/brainstorm/api-designer.md +587 -585
- package/.claude/commands/workflow/brainstorm/artifacts.md +1 -0
- package/.claude/commands/workflow/brainstorm/auto-parallel.md +443 -443
- package/.claude/commands/workflow/brainstorm/data-architect.md +220 -220
- package/.claude/commands/workflow/brainstorm/product-manager.md +200 -200
- package/.claude/commands/workflow/brainstorm/product-owner.md +200 -200
- package/.claude/commands/workflow/brainstorm/scrum-master.md +200 -200
- package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
- package/.claude/commands/workflow/brainstorm/system-architect.md +389 -387
- package/.claude/commands/workflow/brainstorm/ui-designer.md +221 -221
- package/.claude/commands/workflow/brainstorm/ux-expert.md +221 -221
- package/.claude/commands/workflow/debug.md +321 -0
- package/.claude/commands/workflow/execute.md +13 -0
- package/.claude/commands/workflow/init.md +165 -164
- package/.claude/commands/workflow/lite-execute.md +119 -13
- package/.claude/commands/workflow/lite-fix.md +623 -621
- package/.claude/commands/workflow/lite-plan.md +610 -592
- package/.claude/commands/workflow/plan.md +5 -5
- package/.claude/commands/workflow/review-module-cycle.md +2 -0
- package/.claude/commands/workflow/review-session-cycle.md +2 -0
- package/.claude/commands/workflow/review.md +297 -291
- package/.claude/commands/workflow/session/complete.md +153 -500
- package/.claude/commands/workflow/session/list.md +95 -95
- package/.claude/commands/workflow/session/resume.md +60 -60
- package/.claude/commands/workflow/session/start.md +199 -199
- package/.claude/commands/workflow/tdd-plan.md +3 -3
- package/.claude/commands/workflow/tdd-verify.md +23 -9
- package/.claude/commands/workflow/test-cycle-execute.md +2 -0
- package/.claude/commands/workflow/test-fix-gen.md +699 -699
- package/.claude/commands/workflow/tools/conflict-resolution.md +104 -18
- package/.claude/commands/workflow/tools/context-gather.md +436 -434
- package/.claude/commands/workflow/tools/task-generate-agent.md +490 -291
- package/.claude/commands/workflow/tools/task-generate-tdd.md +18 -10
- package/.claude/commands/workflow/tools/test-concept-enhanced.md +2 -1
- package/.claude/commands/workflow/tools/test-context-gather.md +1 -0
- package/.claude/commands/workflow/tools/test-task-generate.md +1 -0
- package/.claude/commands/workflow/ui-design/import-from-code.md +9 -6
- package/.claude/skills/command-guide/SKILL.md +5 -5
- package/.claude/skills/command-guide/index/all-commands.json +1 -1
- package/.claude/skills/command-guide/index/by-category.json +1 -1
- package/.claude/skills/command-guide/index/by-use-case.json +1 -1
- package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +857 -778
- package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +266 -269
- package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +2 -2
- package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +142 -92
- package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +4 -4
- package/.claude/skills/command-guide/reference/agents/code-developer.md +7 -6
- package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +2 -2
- package/.claude/skills/command-guide/reference/agents/context-search-agent.md +31 -32
- package/.claude/skills/command-guide/reference/agents/doc-generator.md +4 -4
- package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
- package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +8 -7
- package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +7 -6
- package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
- package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
- package/.claude/skills/command-guide/reference/commands/memory/docs.md +17 -16
- package/.claude/skills/command-guide/reference/commands/memory/load.md +5 -5
- package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +194 -357
- package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
- package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +4 -4
- package/.claude/skills/command-guide/reference/commands/task/create.md +151 -151
- package/.claude/skills/command-guide/reference/commands/version.md +254 -254
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +585 -585
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +443 -443
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +220 -220
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +387 -387
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +221 -221
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +221 -221
- package/.claude/skills/command-guide/reference/commands/workflow/execute.md +25 -20
- package/.claude/skills/command-guide/reference/commands/workflow/init.md +164 -164
- package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +748 -686
- package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +664 -621
- package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +645 -592
- package/.claude/skills/command-guide/reference/commands/workflow/plan.md +5 -5
- package/.claude/skills/command-guide/reference/commands/workflow/review.md +25 -18
- package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +547 -500
- package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +45 -27
- package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +35 -19
- package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +90 -33
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +3 -3
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +23 -9
- package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +699 -699
- package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +103 -17
- package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +487 -291
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +17 -10
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +1 -1
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +6 -6
- package/.claude/workflows/chinese-response.md +38 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-api.txt +122 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-components.txt +122 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-config.txt +89 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-core.txt +60 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-patterns.txt +70 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-testing.txt +81 -0
- package/.claude/workflows/cli-templates/prompts/rules/tech-rules-agent-prompt.txt +89 -0
- package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +131 -131
- package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +5 -9
- package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +5 -9
- package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +112 -0
- package/.claude/workflows/cli-templates/protocols/write-protocol.md +201 -0
- package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +137 -0
- package/.claude/workflows/cli-templates/schemas/debug-log-json-schema.json +127 -0
- package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +25 -0
- package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +25 -0
- package/.claude/workflows/cli-tools-usage.md +526 -0
- package/{CLAUDE.md → .claude/workflows/coding-philosophy.md} +24 -45
- package/.claude/workflows/context-tools.md +84 -0
- package/.claude/workflows/file-modification.md +64 -0
- package/.claude/workflows/tool-strategy.md +216 -79
- package/.claude/workflows/windows-platform.md +16 -0
- package/.claude/workflows/workflow-architecture.md +942 -942
- package/.codex/AGENTS.md +63 -330
- package/.codex/prompts/debug.md +318 -0
- package/.codex/prompts/execute.md +273 -0
- package/.codex/prompts/lite-execute.md +164 -0
- package/.codex/prompts/lite-plan.md +469 -0
- package/.codex/prompts.zip +0 -0
- package/.gemini/GEMINI.md +25 -164
- package/.qwen/QWEN.md +0 -139
- package/README.md +29 -9
- package/ccw/README.md +30 -6
- package/ccw/bin/ccw-mcp.js +7 -0
- package/ccw/bin/ccw.js +9 -9
- package/ccw/package.json +65 -47
- package/ccw/src/.workflow/.cli-history/history.db +0 -0
- package/ccw/src/.workflow/.cli-history/history.db-shm +0 -0
- package/ccw/src/.workflow/.cli-history/history.db-wal +0 -0
- package/ccw/src/cli.ts +244 -0
- package/ccw/src/commands/cli.ts +740 -0
- package/ccw/src/commands/core-memory.ts +770 -0
- package/ccw/src/commands/hook.ts +315 -0
- package/ccw/src/commands/install.ts +519 -0
- package/ccw/src/commands/{list.js → list.ts} +1 -1
- package/ccw/src/commands/memory.ts +1090 -0
- package/ccw/src/commands/{serve.js → serve.ts} +14 -5
- package/ccw/src/commands/session-path-resolver.ts +372 -0
- package/ccw/src/commands/session.ts +1141 -0
- package/ccw/src/commands/{stop.js → stop.ts} +16 -6
- package/ccw/src/commands/tool.ts +201 -0
- package/ccw/src/commands/{uninstall.js → uninstall.ts} +89 -40
- package/ccw/src/commands/{upgrade.js → upgrade.ts} +68 -23
- package/ccw/src/commands/{view.js → view.ts} +22 -8
- package/ccw/src/config/storage-paths.ts +670 -0
- package/ccw/src/core/cache-manager.ts +294 -0
- package/ccw/src/core/claude-freshness.ts +319 -0
- package/ccw/src/core/core-memory-store.ts +1528 -0
- package/ccw/src/core/{dashboard-generator-patch.js → dashboard-generator-patch.ts} +18 -0
- package/ccw/src/core/{dashboard-generator.js → dashboard-generator.ts} +69 -12
- package/ccw/src/core/data-aggregator.ts +584 -0
- package/ccw/src/core/history-importer.ts +625 -0
- package/ccw/src/core/{lite-scanner.js → lite-scanner-complete.ts} +162 -66
- package/ccw/src/core/lite-scanner.ts +469 -0
- package/ccw/src/core/{manifest.js → manifest.ts} +104 -34
- package/ccw/src/core/memory-embedder-bridge.ts +262 -0
- package/ccw/src/core/memory-store.ts +978 -0
- package/ccw/src/core/routes/ccw-routes.ts +96 -0
- package/ccw/src/core/routes/claude-routes.ts +1183 -0
- package/ccw/src/core/routes/cli-routes.ts +561 -0
- package/ccw/src/core/routes/codexlens-routes.ts +806 -0
- package/ccw/src/core/routes/core-memory-routes.ts +605 -0
- package/ccw/src/core/routes/files-routes.ts +428 -0
- package/ccw/src/core/routes/graph-routes.md +164 -0
- package/ccw/src/core/routes/graph-routes.ts +626 -0
- package/ccw/src/core/routes/help-routes.ts +308 -0
- package/ccw/src/core/routes/hooks-routes.ts +405 -0
- package/ccw/src/core/routes/mcp-routes.ts +1271 -0
- package/ccw/src/core/routes/mcp-routes.ts.backup +550 -0
- package/ccw/src/core/routes/mcp-templates-db.ts +268 -0
- package/ccw/src/core/routes/memory-routes.ts +1206 -0
- package/ccw/src/core/routes/rules-routes.ts +526 -0
- package/ccw/src/core/routes/session-routes.ts +467 -0
- package/ccw/src/core/routes/skills-routes.ts +599 -0
- package/ccw/src/core/routes/status-routes.ts +57 -0
- package/ccw/src/core/routes/system-routes.ts +427 -0
- package/ccw/src/core/server.ts +431 -0
- package/ccw/src/core/session-clustering-service.ts +1258 -0
- package/ccw/src/core/session-scanner.ts +283 -0
- package/ccw/src/core/websocket.ts +190 -0
- package/ccw/src/{index.js → index.ts} +1 -0
- package/ccw/src/mcp-server/index.ts +186 -0
- package/ccw/src/templates/assets/css/github-dark.min.css +10 -0
- package/ccw/src/templates/assets/css/github.min.css +10 -0
- package/ccw/src/templates/assets/js/cytoscape.min.js +32 -0
- package/ccw/src/templates/assets/js/d3.min.js +2 -0
- package/ccw/src/templates/assets/js/highlight.min.js +1244 -0
- package/ccw/src/templates/assets/js/lucide.min.js +12 -0
- package/ccw/src/templates/assets/js/marked.min.js +69 -0
- package/ccw/src/templates/assets/js/tailwind.js +83 -0
- package/ccw/src/templates/dashboard-css/01-base.css +11 -0
- package/ccw/src/templates/dashboard-css/02-session.css +22 -0
- package/ccw/src/templates/dashboard-css/04-lite-tasks.css +10 -0
- package/ccw/src/templates/dashboard-css/06-cards.css +10 -4
- package/ccw/src/templates/dashboard-css/07-managers.css +1178 -7
- package/ccw/src/templates/dashboard-css/09-explorer.css +23 -12
- package/ccw/src/templates/dashboard-css/10-cli-status.css +337 -0
- package/ccw/src/templates/dashboard-css/11-cli-history.css +271 -0
- package/ccw/src/templates/dashboard-css/12-cli-legacy.css +796 -0
- package/ccw/src/templates/dashboard-css/13-cli-ccw.css +199 -0
- package/ccw/src/templates/dashboard-css/14-cli-modals.css +258 -0
- package/ccw/src/templates/dashboard-css/15-cli-endpoints.css +305 -0
- package/ccw/src/templates/dashboard-css/16-cli-session.css +241 -0
- package/ccw/src/templates/dashboard-css/17-cli-conversation.css +283 -0
- package/ccw/src/templates/dashboard-css/18-cli-settings.css +160 -0
- package/ccw/src/templates/dashboard-css/19-cli-native-session.css +496 -0
- package/ccw/src/templates/dashboard-css/20-cli-taskqueue.css +188 -0
- package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +310 -0
- package/ccw/src/templates/dashboard-css/22-cli-semantic.css +240 -0
- package/ccw/src/templates/dashboard-css/23-memory.css +2390 -0
- package/ccw/src/templates/dashboard-css/24-prompt-history.css +1089 -0
- package/ccw/src/templates/dashboard-css/25-skills-rules.css +326 -0
- package/ccw/src/templates/dashboard-css/26-claude-manager.css +908 -0
- package/ccw/src/templates/dashboard-css/27-graph-explorer.css +1678 -0
- package/ccw/src/templates/dashboard-css/28-mcp-manager.css +748 -0
- package/ccw/src/templates/dashboard-css/29-help.css +264 -0
- package/ccw/src/templates/dashboard-css/30-core-memory.css +1700 -0
- package/ccw/src/templates/dashboard-js/api.js +162 -142
- package/ccw/src/templates/dashboard-js/components/carousel.js +4 -4
- package/ccw/src/templates/dashboard-js/components/cli-history.js +876 -0
- package/ccw/src/templates/dashboard-js/components/cli-status.js +978 -0
- package/ccw/src/templates/dashboard-js/components/global-notifications.js +508 -219
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +1277 -282
- package/ccw/src/templates/dashboard-js/components/index-manager.js +302 -0
- package/ccw/src/templates/dashboard-js/components/mcp-manager.js +718 -27
- package/ccw/src/templates/dashboard-js/components/modals.js +66 -0
- package/ccw/src/templates/dashboard-js/components/navigation.js +80 -12
- package/ccw/src/templates/dashboard-js/components/notifications.js +758 -194
- package/ccw/src/templates/dashboard-js/components/storage-manager.js +478 -0
- package/ccw/src/templates/dashboard-js/components/tabs-other.js +157 -6
- package/ccw/src/templates/dashboard-js/components/task-queue-sidebar.js +716 -0
- package/ccw/src/templates/dashboard-js/help-i18n.js +272 -0
- package/ccw/src/templates/dashboard-js/i18n.js +2807 -0
- package/ccw/src/templates/dashboard-js/main.js +15 -0
- package/ccw/src/templates/dashboard-js/state.js +243 -42
- package/ccw/src/templates/dashboard-js/utils.js +47 -1
- package/ccw/src/templates/dashboard-js/views/claude-manager.js +912 -0
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +2272 -0
- package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +964 -0
- package/ccw/src/templates/dashboard-js/views/core-memory-clusters.js +503 -0
- package/ccw/src/templates/dashboard-js/views/core-memory.js +782 -0
- package/ccw/src/templates/dashboard-js/views/explorer.js +888 -852
- package/ccw/src/templates/dashboard-js/views/graph-explorer.js +1157 -0
- package/ccw/src/templates/dashboard-js/views/help.js +856 -0
- package/ccw/src/templates/dashboard-js/views/history.js +337 -0
- package/ccw/src/templates/dashboard-js/views/home.js +61 -15
- package/ccw/src/templates/dashboard-js/views/hook-manager.js +311 -43
- package/ccw/src/templates/dashboard-js/views/lite-tasks.js +204 -28
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2187 -411
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js.backup +1729 -0
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js.new +928 -0
- package/ccw/src/templates/dashboard-js/views/memory.js +1221 -0
- package/ccw/src/templates/dashboard-js/views/prompt-history.js +713 -0
- package/ccw/src/templates/dashboard-js/views/rules-manager.js +828 -0
- package/ccw/src/templates/dashboard-js/views/session-detail.js +54 -53
- package/ccw/src/templates/dashboard-js/views/skills-manager.js +819 -0
- package/ccw/src/templates/dashboard.html +185 -85
- package/ccw/src/templates/hooks-config-example.json +60 -0
- package/ccw/src/tools/classify-folders.ts +245 -0
- package/ccw/src/tools/cli-config-manager.ts +268 -0
- package/ccw/src/tools/cli-executor.ts +2014 -0
- package/ccw/src/tools/cli-history-store.ts +1195 -0
- package/ccw/src/tools/codex-lens.ts +1141 -0
- package/ccw/src/tools/{convert-tokens-to-css.js → convert-tokens-to-css.ts} +73 -23
- package/ccw/src/tools/core-memory.ts +444 -0
- package/ccw/src/tools/detect-changed-modules.ts +325 -0
- package/ccw/src/tools/{discover-design-files.js → discover-design-files.ts} +74 -24
- package/ccw/src/tools/edit-file.ts +568 -0
- package/ccw/src/tools/{generate-module-docs.js → generate-module-docs.ts} +207 -185
- package/ccw/src/tools/{get-modules-by-depth.js → get-modules-by-depth.ts} +120 -79
- package/ccw/src/tools/index.ts +370 -0
- package/ccw/src/tools/native-session-discovery.ts +795 -0
- package/ccw/src/tools/notifier.ts +129 -0
- package/ccw/src/tools/read-file.ts +410 -0
- package/ccw/src/tools/resume-strategy.ts +345 -0
- package/ccw/src/tools/session-content-parser.ts +619 -0
- package/ccw/src/tools/session-manager.ts +1026 -0
- package/ccw/src/tools/smart-context.ts +228 -0
- package/ccw/src/tools/smart-search.ts +2065 -0
- package/ccw/src/tools/smart-search.ts.backup +1233 -0
- package/ccw/src/tools/storage-manager.ts +455 -0
- package/ccw/src/tools/write-file.ts +222 -0
- package/ccw/src/types/config.ts +11 -0
- package/ccw/src/types/index.ts +3 -0
- package/ccw/src/types/session.ts +25 -0
- package/ccw/src/types/tool.ts +41 -0
- package/ccw/src/utils/{browser-launcher.js → browser-launcher.ts} +10 -8
- package/ccw/src/utils/file-utils.ts +48 -0
- package/ccw/src/utils/{path-resolver.js → path-resolver.ts} +114 -78
- package/ccw/src/utils/path-validator.ts +153 -0
- package/ccw/src/utils/{ui.js → ui.ts} +32 -25
- package/codex-lens/pyproject.toml +48 -0
- package/codex-lens/src/codexlens/.workflow/.cli-history/history.db +0 -0
- package/codex-lens/src/codexlens/__init__.py +28 -0
- package/codex-lens/src/codexlens/__main__.py +14 -0
- package/codex-lens/src/codexlens/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/__main__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/errors.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__init__.py +27 -0
- package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/commands.py +1931 -0
- package/codex-lens/src/codexlens/cli/embedding_manager.py +620 -0
- package/codex-lens/src/codexlens/cli/model_manager.py +289 -0
- package/codex-lens/src/codexlens/cli/output.py +124 -0
- package/codex-lens/src/codexlens/config.py +201 -0
- package/codex-lens/src/codexlens/entities.py +121 -0
- package/codex-lens/src/codexlens/errors.py +55 -0
- package/codex-lens/src/codexlens/indexing/README.md +77 -0
- package/codex-lens/src/codexlens/indexing/__init__.py +4 -0
- package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/indexing/symbol_extractor.py +243 -0
- package/codex-lens/src/codexlens/parsers/__init__.py +8 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/encoding.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/encoding.py +202 -0
- package/codex-lens/src/codexlens/parsers/factory.py +256 -0
- package/codex-lens/src/codexlens/parsers/tokenizer.py +98 -0
- package/codex-lens/src/codexlens/parsers/treesitter_parser.py +335 -0
- package/codex-lens/src/codexlens/search/__init__.py +15 -0
- package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/query_parser.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/chain_search.py +647 -0
- package/codex-lens/src/codexlens/search/enrichment.py +150 -0
- package/codex-lens/src/codexlens/search/hybrid_search.py +313 -0
- package/codex-lens/src/codexlens/search/query_parser.py +242 -0
- package/codex-lens/src/codexlens/search/ranking.py +274 -0
- package/codex-lens/src/codexlens/semantic/__init__.py +39 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/code_extractor.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/graph_analyzer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/llm_enhancer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/ann_index.py +414 -0
- package/codex-lens/src/codexlens/semantic/chunker.py +448 -0
- package/codex-lens/src/codexlens/semantic/code_extractor.py +274 -0
- package/codex-lens/src/codexlens/semantic/embedder.py +185 -0
- package/codex-lens/src/codexlens/semantic/vector_store.py +955 -0
- package/codex-lens/src/codexlens/storage/__init__.py +29 -0
- package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/file_cache.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/migration_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/dir_index.py +1850 -0
- package/codex-lens/src/codexlens/storage/file_cache.py +32 -0
- package/codex-lens/src/codexlens/storage/index_tree.py +776 -0
- package/codex-lens/src/codexlens/storage/migration_manager.py +154 -0
- package/codex-lens/src/codexlens/storage/migrations/__init__.py +1 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_001_normalize_keywords.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_002_add_token_metadata.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_003_code_relationships.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_005_cleanup_unused_fields.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_001_normalize_keywords.py +123 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_002_add_token_metadata.py +48 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_004_dual_fts.py +232 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py +196 -0
- package/codex-lens/src/codexlens/storage/path_mapper.py +274 -0
- package/codex-lens/src/codexlens/storage/registry.py +670 -0
- package/codex-lens/src/codexlens/storage/sqlite_store.py +576 -0
- package/codex-lens/src/codexlens/storage/sqlite_utils.py +64 -0
- package/package.json +4 -1
- package/.claude/commands/memory/tech-research.md +0 -477
- package/.claude/scripts/classify-folders.sh +0 -39
- package/.claude/scripts/convert_tokens_to_css.sh +0 -229
- package/.claude/scripts/detect_changed_modules.sh +0 -161
- package/.claude/scripts/discover-design-files.sh +0 -87
- package/.claude/scripts/extract-animations.js +0 -243
- package/.claude/scripts/extract-computed-styles.js +0 -118
- package/.claude/scripts/extract-layout-structure.js +0 -411
- package/.claude/scripts/generate_module_docs.sh +0 -717
- package/.claude/scripts/get_modules_by_depth.sh +0 -170
- package/.claude/scripts/ui-generate-preview.sh +0 -395
- package/.claude/scripts/ui-instantiate-prototypes.sh +0 -815
- package/.claude/scripts/update_module_claude.sh +0 -337
- package/.claude/workflows/context-search-strategy.md +0 -77
- package/.claude/workflows/intelligent-tools-strategy.md +0 -662
- package/ccw/src/cli.js +0 -119
- package/ccw/src/commands/install.js +0 -324
- package/ccw/src/commands/tool.js +0 -138
- package/ccw/src/core/data-aggregator.js +0 -409
- package/ccw/src/core/server.js +0 -2063
- package/ccw/src/core/session-scanner.js +0 -235
- package/ccw/src/tools/classify-folders.js +0 -204
- package/ccw/src/tools/detect-changed-modules.js +0 -288
- package/ccw/src/tools/edit-file.js +0 -266
- package/ccw/src/tools/index.js +0 -176
- package/ccw/src/utils/file-utils.js +0 -48
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
"""Approximate Nearest Neighbor (ANN) index using HNSW algorithm.
|
|
2
|
+
|
|
3
|
+
Provides O(log N) similarity search using hnswlib's Hierarchical Navigable Small World graphs.
|
|
4
|
+
Falls back to brute-force search when hnswlib is not available.
|
|
5
|
+
|
|
6
|
+
Key features:
|
|
7
|
+
- HNSW index for fast approximate nearest neighbor search
|
|
8
|
+
- Persistent index storage (saved alongside SQLite database)
|
|
9
|
+
- Incremental vector addition and deletion
|
|
10
|
+
- Thread-safe operations
|
|
11
|
+
- Cosine similarity metric
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import threading
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import List, Optional, Tuple
|
|
20
|
+
|
|
21
|
+
from codexlens.errors import StorageError
|
|
22
|
+
|
|
23
|
+
from . import SEMANTIC_AVAILABLE
|
|
24
|
+
|
|
25
|
+
if SEMANTIC_AVAILABLE:
|
|
26
|
+
import numpy as np
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
# Try to import hnswlib (optional dependency)
|
|
31
|
+
try:
|
|
32
|
+
import hnswlib
|
|
33
|
+
|
|
34
|
+
HNSWLIB_AVAILABLE = True
|
|
35
|
+
except ImportError:
|
|
36
|
+
HNSWLIB_AVAILABLE = False
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ANNIndex:
|
|
40
|
+
"""HNSW-based approximate nearest neighbor index for vector similarity search.
|
|
41
|
+
|
|
42
|
+
Performance characteristics:
|
|
43
|
+
- Build time: O(N log N) where N is number of vectors
|
|
44
|
+
- Search time: O(log N) approximate
|
|
45
|
+
- Memory: ~(M * 2 * 4 * d) bytes per vector (M=16, d=dimension)
|
|
46
|
+
|
|
47
|
+
Index parameters:
|
|
48
|
+
- space: cosine (cosine similarity metric)
|
|
49
|
+
- M: 16 (max connections per node - balance between speed and recall)
|
|
50
|
+
- ef_construction: 200 (search width during build - higher = better quality)
|
|
51
|
+
- ef: 50 (search width during query - higher = better recall)
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
index_path: Path,
|
|
57
|
+
dim: int,
|
|
58
|
+
initial_capacity: int = 50000,
|
|
59
|
+
auto_save: bool = False,
|
|
60
|
+
expansion_threshold: float = 0.8,
|
|
61
|
+
) -> None:
|
|
62
|
+
"""Initialize ANN index.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
index_path: Path to SQLite database (index will be saved as _vectors.hnsw)
|
|
66
|
+
dim: Dimension of embedding vectors
|
|
67
|
+
initial_capacity: Initial maximum elements capacity (default: 50000)
|
|
68
|
+
auto_save: Whether to automatically save index after operations (default: False)
|
|
69
|
+
expansion_threshold: Capacity threshold to trigger auto-expansion (default: 0.8)
|
|
70
|
+
|
|
71
|
+
Raises:
|
|
72
|
+
ImportError: If required dependencies are not available
|
|
73
|
+
ValueError: If dimension or capacity is invalid
|
|
74
|
+
"""
|
|
75
|
+
if not SEMANTIC_AVAILABLE:
|
|
76
|
+
raise ImportError(
|
|
77
|
+
"Semantic search dependencies not available. "
|
|
78
|
+
"Install with: pip install codexlens[semantic]"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if not HNSWLIB_AVAILABLE:
|
|
82
|
+
raise ImportError(
|
|
83
|
+
"hnswlib is required for ANN index. "
|
|
84
|
+
"Install with: pip install hnswlib"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if dim <= 0:
|
|
88
|
+
raise ValueError(f"Invalid dimension: {dim}")
|
|
89
|
+
|
|
90
|
+
if initial_capacity <= 0:
|
|
91
|
+
raise ValueError(f"Invalid initial capacity: {initial_capacity}")
|
|
92
|
+
|
|
93
|
+
if not 0.0 < expansion_threshold < 1.0:
|
|
94
|
+
raise ValueError(
|
|
95
|
+
f"Invalid expansion threshold: {expansion_threshold}. Must be between 0 and 1."
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
self.index_path = Path(index_path)
|
|
99
|
+
self.dim = dim
|
|
100
|
+
|
|
101
|
+
# Derive HNSW index path from database path
|
|
102
|
+
# e.g., /path/to/_index.db -> /path/to/_index_vectors.hnsw
|
|
103
|
+
# This ensures unique HNSW files for each database
|
|
104
|
+
db_stem = self.index_path.stem # e.g., "_index" or "tmp123"
|
|
105
|
+
self.hnsw_path = self.index_path.parent / f"{db_stem}_vectors.hnsw"
|
|
106
|
+
|
|
107
|
+
# HNSW parameters
|
|
108
|
+
self.space = "cosine" # Cosine similarity metric
|
|
109
|
+
self.M = 16 # Max connections per node (16 is good balance)
|
|
110
|
+
self.ef_construction = 200 # Build-time search width (higher = better quality)
|
|
111
|
+
self.ef = 50 # Query-time search width (higher = better recall)
|
|
112
|
+
|
|
113
|
+
# Memory management parameters
|
|
114
|
+
self._auto_save = auto_save
|
|
115
|
+
self._expansion_threshold = expansion_threshold
|
|
116
|
+
|
|
117
|
+
# Thread safety
|
|
118
|
+
self._lock = threading.RLock()
|
|
119
|
+
|
|
120
|
+
# HNSW index instance
|
|
121
|
+
self._index: Optional[hnswlib.Index] = None
|
|
122
|
+
self._max_elements = initial_capacity # Initial capacity (reduced from 1M to 50K)
|
|
123
|
+
self._current_count = 0 # Track number of vectors
|
|
124
|
+
|
|
125
|
+
logger.info(
|
|
126
|
+
f"Initialized ANNIndex with capacity={initial_capacity}, "
|
|
127
|
+
f"auto_save={auto_save}, expansion_threshold={expansion_threshold}"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def _ensure_index(self) -> None:
|
|
131
|
+
"""Ensure HNSW index is initialized (lazy initialization)."""
|
|
132
|
+
if self._index is None:
|
|
133
|
+
self._index = hnswlib.Index(space=self.space, dim=self.dim)
|
|
134
|
+
self._index.init_index(
|
|
135
|
+
max_elements=self._max_elements,
|
|
136
|
+
ef_construction=self.ef_construction,
|
|
137
|
+
M=self.M,
|
|
138
|
+
)
|
|
139
|
+
self._index.set_ef(self.ef)
|
|
140
|
+
self._current_count = 0
|
|
141
|
+
logger.debug(f"Created new HNSW index with capacity {self._max_elements}")
|
|
142
|
+
|
|
143
|
+
def _auto_expand_if_needed(self, additional_count: int) -> None:
|
|
144
|
+
"""Auto-expand index capacity if threshold is reached.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
additional_count: Number of vectors to be added
|
|
148
|
+
|
|
149
|
+
Note:
|
|
150
|
+
This is called internally by add_vectors and is thread-safe.
|
|
151
|
+
"""
|
|
152
|
+
usage_ratio = (self._current_count + additional_count) / self._max_elements
|
|
153
|
+
|
|
154
|
+
if usage_ratio >= self._expansion_threshold:
|
|
155
|
+
# Calculate new capacity (2x current or enough to fit new vectors)
|
|
156
|
+
new_capacity = max(
|
|
157
|
+
self._max_elements * 2,
|
|
158
|
+
self._current_count + additional_count,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
logger.info(
|
|
162
|
+
f"Expanding index capacity: {self._max_elements} -> {new_capacity} "
|
|
163
|
+
f"(usage: {usage_ratio:.1%}, threshold: {self._expansion_threshold:.1%})"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
self._index.resize_index(new_capacity)
|
|
167
|
+
self._max_elements = new_capacity
|
|
168
|
+
|
|
169
|
+
def add_vectors(self, ids: List[int], vectors: np.ndarray) -> None:
|
|
170
|
+
"""Add vectors to the index.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
ids: List of vector IDs (must be unique)
|
|
174
|
+
vectors: Numpy array of shape (N, dim) where N = len(ids)
|
|
175
|
+
|
|
176
|
+
Raises:
|
|
177
|
+
ValueError: If shapes don't match or vectors are invalid
|
|
178
|
+
StorageError: If index operation fails
|
|
179
|
+
"""
|
|
180
|
+
if len(ids) == 0:
|
|
181
|
+
return
|
|
182
|
+
|
|
183
|
+
if vectors.shape[0] != len(ids):
|
|
184
|
+
raise ValueError(
|
|
185
|
+
f"Number of vectors ({vectors.shape[0]}) must match number of IDs ({len(ids)})"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
if vectors.shape[1] != self.dim:
|
|
189
|
+
raise ValueError(
|
|
190
|
+
f"Vector dimension ({vectors.shape[1]}) must match index dimension ({self.dim})"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
with self._lock:
|
|
194
|
+
try:
|
|
195
|
+
self._ensure_index()
|
|
196
|
+
|
|
197
|
+
# Auto-expand if threshold reached
|
|
198
|
+
self._auto_expand_if_needed(len(ids))
|
|
199
|
+
|
|
200
|
+
# Ensure vectors are C-contiguous float32 (hnswlib requirement)
|
|
201
|
+
if not vectors.flags['C_CONTIGUOUS'] or vectors.dtype != np.float32:
|
|
202
|
+
vectors = np.ascontiguousarray(vectors, dtype=np.float32)
|
|
203
|
+
|
|
204
|
+
# Add vectors to index
|
|
205
|
+
self._index.add_items(vectors, ids)
|
|
206
|
+
self._current_count += len(ids)
|
|
207
|
+
|
|
208
|
+
logger.debug(
|
|
209
|
+
f"Added {len(ids)} vectors to index "
|
|
210
|
+
f"(total: {self._current_count}/{self._max_elements})"
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# Auto-save if enabled
|
|
214
|
+
if self._auto_save:
|
|
215
|
+
self.save()
|
|
216
|
+
|
|
217
|
+
except Exception as e:
|
|
218
|
+
raise StorageError(f"Failed to add vectors to ANN index: {e}")
|
|
219
|
+
|
|
220
|
+
def remove_vectors(self, ids: List[int]) -> None:
|
|
221
|
+
"""Remove vectors from the index by marking them as deleted.
|
|
222
|
+
|
|
223
|
+
Note: hnswlib uses soft deletion (mark_deleted). Vectors are not
|
|
224
|
+
physically removed but will be excluded from search results.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
ids: List of vector IDs to remove
|
|
228
|
+
|
|
229
|
+
Raises:
|
|
230
|
+
StorageError: If index operation fails
|
|
231
|
+
"""
|
|
232
|
+
if len(ids) == 0:
|
|
233
|
+
return
|
|
234
|
+
|
|
235
|
+
with self._lock:
|
|
236
|
+
try:
|
|
237
|
+
if self._index is None or self._current_count == 0:
|
|
238
|
+
return # Nothing to remove
|
|
239
|
+
|
|
240
|
+
# Mark vectors as deleted
|
|
241
|
+
deleted_count = 0
|
|
242
|
+
for vec_id in ids:
|
|
243
|
+
try:
|
|
244
|
+
self._index.mark_deleted(vec_id)
|
|
245
|
+
deleted_count += 1
|
|
246
|
+
except RuntimeError:
|
|
247
|
+
# ID not found - ignore (idempotent deletion)
|
|
248
|
+
pass
|
|
249
|
+
|
|
250
|
+
logger.debug(f"Marked {deleted_count}/{len(ids)} vectors as deleted")
|
|
251
|
+
|
|
252
|
+
# Auto-save if enabled
|
|
253
|
+
if self._auto_save and deleted_count > 0:
|
|
254
|
+
self.save()
|
|
255
|
+
|
|
256
|
+
except Exception as e:
|
|
257
|
+
raise StorageError(f"Failed to remove vectors from ANN index: {e}")
|
|
258
|
+
|
|
259
|
+
def search(
|
|
260
|
+
self, query: np.ndarray, top_k: int = 10
|
|
261
|
+
) -> Tuple[List[int], List[float]]:
|
|
262
|
+
"""Search for nearest neighbors.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
query: Query vector of shape (dim,) or (1, dim)
|
|
266
|
+
top_k: Number of nearest neighbors to return
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
Tuple of (ids, distances) where:
|
|
270
|
+
- ids: List of vector IDs ordered by similarity
|
|
271
|
+
- distances: List of cosine distances (lower = more similar)
|
|
272
|
+
|
|
273
|
+
Raises:
|
|
274
|
+
ValueError: If query shape is invalid
|
|
275
|
+
StorageError: If search operation fails
|
|
276
|
+
"""
|
|
277
|
+
# Validate query shape
|
|
278
|
+
if query.ndim == 1:
|
|
279
|
+
query = query.reshape(1, -1)
|
|
280
|
+
|
|
281
|
+
if query.shape[0] != 1:
|
|
282
|
+
raise ValueError(
|
|
283
|
+
f"Query must be a single vector, got shape {query.shape}"
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
if query.shape[1] != self.dim:
|
|
287
|
+
raise ValueError(
|
|
288
|
+
f"Query dimension ({query.shape[1]}) must match index dimension ({self.dim})"
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
with self._lock:
|
|
292
|
+
try:
|
|
293
|
+
if self._index is None or self._current_count == 0:
|
|
294
|
+
return [], [] # Empty index
|
|
295
|
+
|
|
296
|
+
# Perform kNN search
|
|
297
|
+
labels, distances = self._index.knn_query(query, k=top_k)
|
|
298
|
+
|
|
299
|
+
# Convert to lists and flatten (knn_query returns 2D arrays)
|
|
300
|
+
ids = labels[0].tolist()
|
|
301
|
+
dists = distances[0].tolist()
|
|
302
|
+
|
|
303
|
+
return ids, dists
|
|
304
|
+
|
|
305
|
+
except Exception as e:
|
|
306
|
+
raise StorageError(f"Failed to search ANN index: {e}")
|
|
307
|
+
|
|
308
|
+
def save(self) -> None:
|
|
309
|
+
"""Save index to disk.
|
|
310
|
+
|
|
311
|
+
Index is saved to [db_path_directory]/_vectors.hnsw
|
|
312
|
+
|
|
313
|
+
Raises:
|
|
314
|
+
StorageError: If save operation fails
|
|
315
|
+
"""
|
|
316
|
+
with self._lock:
|
|
317
|
+
try:
|
|
318
|
+
if self._index is None or self._current_count == 0:
|
|
319
|
+
logger.debug("Skipping save: index is empty")
|
|
320
|
+
return # Nothing to save
|
|
321
|
+
|
|
322
|
+
# Ensure parent directory exists
|
|
323
|
+
self.hnsw_path.parent.mkdir(parents=True, exist_ok=True)
|
|
324
|
+
|
|
325
|
+
# Save index
|
|
326
|
+
self._index.save_index(str(self.hnsw_path))
|
|
327
|
+
|
|
328
|
+
logger.debug(
|
|
329
|
+
f"Saved index to {self.hnsw_path} "
|
|
330
|
+
f"({self._current_count} vectors, capacity: {self._max_elements})"
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
except Exception as e:
|
|
334
|
+
raise StorageError(f"Failed to save ANN index: {e}")
|
|
335
|
+
|
|
336
|
+
def load(self) -> bool:
|
|
337
|
+
"""Load index from disk.
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
True if index was loaded successfully, False if index file doesn't exist
|
|
341
|
+
|
|
342
|
+
Raises:
|
|
343
|
+
StorageError: If load operation fails
|
|
344
|
+
"""
|
|
345
|
+
with self._lock:
|
|
346
|
+
try:
|
|
347
|
+
if not self.hnsw_path.exists():
|
|
348
|
+
logger.debug(f"Index file not found: {self.hnsw_path}")
|
|
349
|
+
return False # Index file doesn't exist (not an error)
|
|
350
|
+
|
|
351
|
+
# Create fresh index object for loading (don't call init_index first)
|
|
352
|
+
self._index = hnswlib.Index(space=self.space, dim=self.dim)
|
|
353
|
+
|
|
354
|
+
# Load index from disk
|
|
355
|
+
# Note: max_elements here is just for initial allocation, can expand later
|
|
356
|
+
self._index.load_index(str(self.hnsw_path), max_elements=self._max_elements)
|
|
357
|
+
|
|
358
|
+
# Update count and capacity from loaded index
|
|
359
|
+
self._current_count = self._index.get_current_count()
|
|
360
|
+
self._max_elements = self._index.get_max_elements()
|
|
361
|
+
|
|
362
|
+
# Set query-time ef parameter
|
|
363
|
+
self._index.set_ef(self.ef)
|
|
364
|
+
|
|
365
|
+
logger.info(
|
|
366
|
+
f"Loaded index from {self.hnsw_path} "
|
|
367
|
+
f"({self._current_count} vectors, capacity: {self._max_elements})"
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
return True
|
|
371
|
+
|
|
372
|
+
except Exception as e:
|
|
373
|
+
raise StorageError(f"Failed to load ANN index: {e}")
|
|
374
|
+
|
|
375
|
+
def count(self) -> int:
|
|
376
|
+
"""Get number of vectors in the index.
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
Number of vectors currently in the index
|
|
380
|
+
"""
|
|
381
|
+
with self._lock:
|
|
382
|
+
return self._current_count
|
|
383
|
+
|
|
384
|
+
@property
|
|
385
|
+
def capacity(self) -> int:
|
|
386
|
+
"""Get current maximum capacity of the index.
|
|
387
|
+
|
|
388
|
+
Returns:
|
|
389
|
+
Maximum number of vectors the index can hold before expansion
|
|
390
|
+
"""
|
|
391
|
+
with self._lock:
|
|
392
|
+
return self._max_elements
|
|
393
|
+
|
|
394
|
+
@property
|
|
395
|
+
def usage_ratio(self) -> float:
|
|
396
|
+
"""Get current usage ratio (count / capacity).
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
Usage ratio between 0.0 and 1.0
|
|
400
|
+
"""
|
|
401
|
+
with self._lock:
|
|
402
|
+
if self._max_elements == 0:
|
|
403
|
+
return 0.0
|
|
404
|
+
return self._current_count / self._max_elements
|
|
405
|
+
|
|
406
|
+
@property
|
|
407
|
+
def is_loaded(self) -> bool:
|
|
408
|
+
"""Check if index is loaded and ready for use.
|
|
409
|
+
|
|
410
|
+
Returns:
|
|
411
|
+
True if index is loaded, False otherwise
|
|
412
|
+
"""
|
|
413
|
+
with self._lock:
|
|
414
|
+
return self._index is not None and self._current_count > 0
|