codevault 1.8.3 → 1.8.5
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/README.md +33 -5
- package/dist/chunking/file-grouper.d.ts +1 -1
- package/dist/chunking/file-grouper.d.ts.map +1 -1
- package/dist/chunking/file-grouper.js +3 -3
- package/dist/chunking/file-grouper.js.map +1 -1
- package/dist/chunking/semantic-chunker.d.ts +1 -1
- package/dist/chunking/semantic-chunker.d.ts.map +1 -1
- package/dist/chunking/token-counter.d.ts +1 -1
- package/dist/chunking/token-counter.d.ts.map +1 -1
- package/dist/chunking/token-counter.js +16 -10
- package/dist/chunking/token-counter.js.map +1 -1
- package/dist/cli/commands/ask-cmd.js +15 -15
- package/dist/cli/commands/ask-cmd.js.map +1 -1
- package/dist/cli/commands/chat-cmd.d.ts.map +1 -1
- package/dist/cli/commands/chat-cmd.js +40 -40
- package/dist/cli/commands/chat-cmd.js.map +1 -1
- package/dist/cli/commands/config-cmd.d.ts.map +1 -1
- package/dist/cli/commands/config-cmd.js +61 -52
- package/dist/cli/commands/config-cmd.js.map +1 -1
- package/dist/cli/commands/context.d.ts.map +1 -1
- package/dist/cli/commands/context.js +20 -11
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/index-cmd.d.ts.map +1 -1
- package/dist/cli/commands/index-cmd.js +109 -85
- package/dist/cli/commands/index-cmd.js.map +1 -1
- package/dist/cli/commands/info-cmd.d.ts.map +1 -1
- package/dist/cli/commands/info-cmd.js +12 -11
- package/dist/cli/commands/info-cmd.js.map +1 -1
- package/dist/cli/commands/interactive-config.d.ts.map +1 -1
- package/dist/cli/commands/interactive-config.js +60 -20
- package/dist/cli/commands/interactive-config.js.map +1 -1
- package/dist/cli/commands/search-cmd.d.ts.map +1 -1
- package/dist/cli/commands/search-cmd.js +22 -11
- package/dist/cli/commands/search-cmd.js.map +1 -1
- package/dist/cli/commands/search-with-code-cmd.d.ts.map +1 -1
- package/dist/cli/commands/search-with-code-cmd.js +25 -16
- package/dist/cli/commands/search-with-code-cmd.js.map +1 -1
- package/dist/cli/commands/update-cmd.d.ts.map +1 -1
- package/dist/cli/commands/update-cmd.js +16 -7
- package/dist/cli/commands/update-cmd.js.map +1 -1
- package/dist/cli/commands/watch-cmd.d.ts.map +1 -1
- package/dist/cli/commands/watch-cmd.js +21 -11
- package/dist/cli/commands/watch-cmd.js.map +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils.d.ts +56 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +98 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/cli.js +0 -0
- package/dist/codemap/io.js.map +1 -1
- package/dist/config/constants.d.ts +4 -0
- package/dist/config/constants.d.ts.map +1 -1
- package/dist/config/constants.js +2 -0
- package/dist/config/constants.js.map +1 -1
- package/dist/config/loader.js.map +1 -1
- package/dist/context/packs.d.ts +2 -2
- package/dist/context/packs.d.ts.map +1 -1
- package/dist/context/packs.js +7 -4
- package/dist/context/packs.js.map +1 -1
- package/dist/core/IndexerEngine.d.ts +2 -0
- package/dist/core/IndexerEngine.d.ts.map +1 -1
- package/dist/core/IndexerEngine.js +34 -26
- package/dist/core/IndexerEngine.js.map +1 -1
- package/dist/core/SearchService.d.ts +2 -1
- package/dist/core/SearchService.d.ts.map +1 -1
- package/dist/core/SearchService.js +25 -18
- package/dist/core/SearchService.js.map +1 -1
- package/dist/core/batch-indexer.d.ts +4 -3
- package/dist/core/batch-indexer.d.ts.map +1 -1
- package/dist/core/batch-indexer.js +32 -35
- package/dist/core/batch-indexer.js.map +1 -1
- package/dist/core/indexing/FileProcessor.d.ts +1 -0
- package/dist/core/indexing/FileProcessor.d.ts.map +1 -1
- package/dist/core/indexing/FileProcessor.js +32 -9
- package/dist/core/indexing/FileProcessor.js.map +1 -1
- package/dist/core/indexing/IndexContext.d.ts +6 -4
- package/dist/core/indexing/IndexContext.d.ts.map +1 -1
- package/dist/core/indexing/IndexContext.js +3 -3
- package/dist/core/indexing/IndexContext.js.map +1 -1
- package/dist/core/indexing/IndexFinalizationStage.d.ts +6 -1
- package/dist/core/indexing/IndexFinalizationStage.d.ts.map +1 -1
- package/dist/core/indexing/IndexFinalizationStage.js +22 -3
- package/dist/core/indexing/IndexFinalizationStage.js.map +1 -1
- package/dist/core/indexing/IndexState.d.ts +3 -8
- package/dist/core/indexing/IndexState.d.ts.map +1 -1
- package/dist/core/indexing/IndexState.js.map +1 -1
- package/dist/core/indexing/PersistManager.d.ts +1 -1
- package/dist/core/indexing/PersistManager.d.ts.map +1 -1
- package/dist/core/indexing/PersistManager.js +17 -17
- package/dist/core/indexing/PersistManager.js.map +1 -1
- package/dist/core/indexing/chunk-pipeline.d.ts +33 -7
- package/dist/core/indexing/chunk-pipeline.d.ts.map +1 -1
- package/dist/core/indexing/chunk-pipeline.js +20 -8
- package/dist/core/indexing/chunk-pipeline.js.map +1 -1
- package/dist/core/metadata.d.ts +1 -1
- package/dist/core/metadata.d.ts.map +1 -1
- package/dist/core/metadata.js +1 -1
- package/dist/core/metadata.js.map +1 -1
- package/dist/core/search/CandidateRetriever.d.ts +1 -1
- package/dist/core/search/CandidateRetriever.d.ts.map +1 -1
- package/dist/core/search/CandidateRetriever.js +7 -5
- package/dist/core/search/CandidateRetriever.js.map +1 -1
- package/dist/core/search/HybridFusion.d.ts +1 -2
- package/dist/core/search/HybridFusion.d.ts.map +1 -1
- package/dist/core/search/HybridFusion.js +5 -17
- package/dist/core/search/HybridFusion.js.map +1 -1
- package/dist/core/search/ResultMapper.d.ts +0 -1
- package/dist/core/search/ResultMapper.d.ts.map +1 -1
- package/dist/core/search/ResultMapper.js +3 -14
- package/dist/core/search/ResultMapper.js.map +1 -1
- package/dist/core/search/SearchContextManager.d.ts +4 -1
- package/dist/core/search/SearchContextManager.d.ts.map +1 -1
- package/dist/core/search/SearchContextManager.js +19 -6
- package/dist/core/search/SearchContextManager.js.map +1 -1
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/search.js +9 -4
- package/dist/core/search.js.map +1 -1
- package/dist/core/types.d.ts +2 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/database/db.d.ts +14 -14
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +14 -14
- package/dist/database/db.js.map +1 -1
- package/dist/indexer/merkle.js +1 -1
- package/dist/indexer/merkle.js.map +1 -1
- package/dist/languages/rules.d.ts +2 -1
- package/dist/languages/rules.d.ts.map +1 -1
- package/dist/languages/rules.js +14 -5
- package/dist/languages/rules.js.map +1 -1
- package/dist/languages/tree-sitter-loader.d.ts +24 -24
- package/dist/languages/tree-sitter-loader.d.ts.map +1 -1
- package/dist/languages/tree-sitter-loader.js +14 -10
- package/dist/languages/tree-sitter-loader.js.map +1 -1
- package/dist/mcp/handlers/context.d.ts +5 -11
- package/dist/mcp/handlers/context.d.ts.map +1 -1
- package/dist/mcp/handlers/context.js.map +1 -1
- package/dist/mcp/handlers/project.d.ts +9 -27
- package/dist/mcp/handlers/project.d.ts.map +1 -1
- package/dist/mcp/handlers/search.d.ts +24 -18
- package/dist/mcp/handlers/search.d.ts.map +1 -1
- package/dist/mcp/handlers/search.js +8 -2
- package/dist/mcp/handlers/search.js.map +1 -1
- package/dist/mcp/handlers/synthesis.d.ts +15 -11
- package/dist/mcp/handlers/synthesis.d.ts.map +1 -1
- package/dist/mcp/handlers/synthesis.js +4 -1
- package/dist/mcp/handlers/synthesis.js.map +1 -1
- package/dist/mcp/schemas.d.ts +2 -2
- package/dist/mcp/tools/ask-codebase.d.ts +10 -28
- package/dist/mcp/tools/ask-codebase.d.ts.map +1 -1
- package/dist/mcp/tools/ask-codebase.js +1 -1
- package/dist/mcp/tools/ask-codebase.js.map +1 -1
- package/dist/mcp/tools/use-context-pack.d.ts +14 -23
- package/dist/mcp/tools/use-context-pack.d.ts.map +1 -1
- package/dist/mcp/tools/use-context-pack.js +4 -3
- package/dist/mcp/tools/use-context-pack.js.map +1 -1
- package/dist/mcp-server.d.ts +1 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +39 -24
- package/dist/mcp-server.js.map +1 -1
- package/dist/providers/base.d.ts +3 -2
- package/dist/providers/base.d.ts.map +1 -1
- package/dist/providers/base.js +3 -10
- package/dist/providers/base.js.map +1 -1
- package/dist/providers/chat-llm.d.ts +3 -2
- package/dist/providers/chat-llm.d.ts.map +1 -1
- package/dist/providers/chat-llm.js +13 -9
- package/dist/providers/chat-llm.js.map +1 -1
- package/dist/providers/mock.d.ts.map +1 -1
- package/dist/providers/mock.js +6 -5
- package/dist/providers/mock.js.map +1 -1
- package/dist/providers/openai.d.ts +2 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +15 -19
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/token-counter.d.ts.map +1 -1
- package/dist/providers/token-counter.js +11 -3
- package/dist/providers/token-counter.js.map +1 -1
- package/dist/ranking/api-reranker.d.ts +1 -1
- package/dist/ranking/api-reranker.d.ts.map +1 -1
- package/dist/ranking/api-reranker.js +50 -13
- package/dist/ranking/api-reranker.js.map +1 -1
- package/dist/ranking/symbol-boost.d.ts.map +1 -1
- package/dist/ranking/symbol-boost.js +4 -11
- package/dist/ranking/symbol-boost.js.map +1 -1
- package/dist/search/bm25.d.ts +10 -0
- package/dist/search/bm25.d.ts.map +1 -1
- package/dist/search/bm25.js +16 -0
- package/dist/search/bm25.js.map +1 -1
- package/dist/search/hybrid.js.map +1 -1
- package/dist/search/scope.d.ts.map +1 -1
- package/dist/search/scope.js +3 -2
- package/dist/search/scope.js.map +1 -1
- package/dist/storage/encrypted-chunks.d.ts +3 -0
- package/dist/storage/encrypted-chunks.d.ts.map +1 -1
- package/dist/storage/encrypted-chunks.js +126 -47
- package/dist/storage/encrypted-chunks.js.map +1 -1
- package/dist/symbols/extract.d.ts.map +1 -1
- package/dist/symbols/extract.js +3 -2
- package/dist/symbols/extract.js.map +1 -1
- package/dist/symbols/graph.d.ts.map +1 -1
- package/dist/symbols/graph.js +14 -8
- package/dist/symbols/graph.js.map +1 -1
- package/dist/synthesis/conversational-synthesizer.d.ts +2 -1
- package/dist/synthesis/conversational-synthesizer.d.ts.map +1 -1
- package/dist/synthesis/conversational-synthesizer.js +6 -1
- package/dist/synthesis/conversational-synthesizer.js.map +1 -1
- package/dist/synthesis/markdown-formatter.d.ts.map +1 -1
- package/dist/synthesis/markdown-formatter.js +1 -1
- package/dist/synthesis/markdown-formatter.js.map +1 -1
- package/dist/synthesis/prompt-builder.d.ts.map +1 -1
- package/dist/synthesis/prompt-builder.js +42 -15
- package/dist/synthesis/prompt-builder.js.map +1 -1
- package/dist/synthesis/synthesizer.d.ts.map +1 -1
- package/dist/synthesis/synthesizer.js +23 -10
- package/dist/synthesis/synthesizer.js.map +1 -1
- package/dist/tests/api-reranker.test.d.ts +2 -0
- package/dist/tests/api-reranker.test.d.ts.map +1 -0
- package/dist/tests/api-reranker.test.js +575 -0
- package/dist/tests/api-reranker.test.js.map +1 -0
- package/dist/tests/bm25.test.d.ts +2 -0
- package/dist/tests/bm25.test.d.ts.map +1 -0
- package/dist/tests/bm25.test.js +340 -0
- package/dist/tests/bm25.test.js.map +1 -0
- package/dist/tests/chunking/file-grouper.test.d.ts +2 -0
- package/dist/tests/chunking/file-grouper.test.d.ts.map +1 -0
- package/dist/tests/chunking/file-grouper.test.js +495 -0
- package/dist/tests/chunking/file-grouper.test.js.map +1 -0
- package/dist/tests/chunking/semantic-chunker.test.d.ts +2 -0
- package/dist/tests/chunking/semantic-chunker.test.d.ts.map +1 -0
- package/dist/tests/chunking/semantic-chunker.test.js +509 -0
- package/dist/tests/chunking/semantic-chunker.test.js.map +1 -0
- package/dist/tests/chunking/token-counter.test.d.ts +2 -0
- package/dist/tests/chunking/token-counter.test.d.ts.map +1 -0
- package/dist/tests/chunking/token-counter.test.js +441 -0
- package/dist/tests/chunking/token-counter.test.js.map +1 -0
- package/dist/tests/cli/ask-cmd.test.d.ts +2 -0
- package/dist/tests/cli/ask-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/ask-cmd.test.js +152 -0
- package/dist/tests/cli/ask-cmd.test.js.map +1 -0
- package/dist/tests/cli/chat-cmd.test.d.ts +2 -0
- package/dist/tests/cli/chat-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/chat-cmd.test.js +118 -0
- package/dist/tests/cli/chat-cmd.test.js.map +1 -0
- package/dist/tests/cli/config-cmd.test.d.ts +2 -0
- package/dist/tests/cli/config-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/config-cmd.test.js +226 -0
- package/dist/tests/cli/config-cmd.test.js.map +1 -0
- package/dist/tests/cli/context.test.d.ts +2 -0
- package/dist/tests/cli/context.test.d.ts.map +1 -0
- package/dist/tests/cli/context.test.js +158 -0
- package/dist/tests/cli/context.test.js.map +1 -0
- package/dist/tests/cli/index-cmd.test.d.ts +2 -0
- package/dist/tests/cli/index-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/index-cmd.test.js +89 -0
- package/dist/tests/cli/index-cmd.test.js.map +1 -0
- package/dist/tests/cli/index.test.d.ts +2 -0
- package/dist/tests/cli/index.test.d.ts.map +1 -0
- package/dist/tests/cli/index.test.js +167 -0
- package/dist/tests/cli/index.test.js.map +1 -0
- package/dist/tests/cli/info-cmd.test.d.ts +2 -0
- package/dist/tests/cli/info-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/info-cmd.test.js +47 -0
- package/dist/tests/cli/info-cmd.test.js.map +1 -0
- package/dist/tests/cli/interactive-config.test.d.ts +2 -0
- package/dist/tests/cli/interactive-config.test.d.ts.map +1 -0
- package/dist/tests/cli/interactive-config.test.js +30 -0
- package/dist/tests/cli/interactive-config.test.js.map +1 -0
- package/dist/tests/cli/mcp-cmd.test.d.ts +2 -0
- package/dist/tests/cli/mcp-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/mcp-cmd.test.js +47 -0
- package/dist/tests/cli/mcp-cmd.test.js.map +1 -0
- package/dist/tests/cli/search-cmd.test.d.ts +2 -0
- package/dist/tests/cli/search-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/search-cmd.test.js +120 -0
- package/dist/tests/cli/search-cmd.test.js.map +1 -0
- package/dist/tests/cli/search-with-code-cmd.test.d.ts +2 -0
- package/dist/tests/cli/search-with-code-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/search-with-code-cmd.test.js +140 -0
- package/dist/tests/cli/search-with-code-cmd.test.js.map +1 -0
- package/dist/tests/cli/update-cmd.test.d.ts +2 -0
- package/dist/tests/cli/update-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/update-cmd.test.js +75 -0
- package/dist/tests/cli/update-cmd.test.js.map +1 -0
- package/dist/tests/cli/utils.test.d.ts +2 -0
- package/dist/tests/cli/utils.test.d.ts.map +1 -0
- package/dist/tests/cli/utils.test.js +119 -0
- package/dist/tests/cli/utils.test.js.map +1 -0
- package/dist/tests/cli/watch-cmd.test.d.ts +2 -0
- package/dist/tests/cli/watch-cmd.test.d.ts.map +1 -0
- package/dist/tests/cli/watch-cmd.test.js +84 -0
- package/dist/tests/cli/watch-cmd.test.js.map +1 -0
- package/dist/tests/cli-ui.test.d.ts +2 -0
- package/dist/tests/cli-ui.test.d.ts.map +1 -0
- package/dist/tests/cli-ui.test.js +608 -0
- package/dist/tests/cli-ui.test.js.map +1 -0
- package/dist/tests/codemap-io.test.d.ts +2 -0
- package/dist/tests/codemap-io.test.d.ts.map +1 -0
- package/dist/tests/codemap-io.test.js +992 -0
- package/dist/tests/codemap-io.test.js.map +1 -0
- package/dist/tests/config/apply-env.test.d.ts +2 -0
- package/dist/tests/config/apply-env.test.d.ts.map +1 -0
- package/dist/tests/config/apply-env.test.js +717 -0
- package/dist/tests/config/apply-env.test.js.map +1 -0
- package/dist/tests/config/constants.test.d.ts +2 -0
- package/dist/tests/config/constants.test.d.ts.map +1 -0
- package/dist/tests/config/constants.test.js +406 -0
- package/dist/tests/config/constants.test.js.map +1 -0
- package/dist/tests/config/loader.test.d.ts +2 -0
- package/dist/tests/config/loader.test.d.ts.map +1 -0
- package/dist/tests/config/loader.test.js +716 -0
- package/dist/tests/config/loader.test.js.map +1 -0
- package/dist/tests/config/resolver.test.d.ts +2 -0
- package/dist/tests/config/resolver.test.d.ts.map +1 -0
- package/dist/tests/config/resolver.test.js +402 -0
- package/dist/tests/config/resolver.test.js.map +1 -0
- package/dist/tests/config/types.test.d.ts +2 -0
- package/dist/tests/config/types.test.d.ts.map +1 -0
- package/dist/tests/config/types.test.js +460 -0
- package/dist/tests/config/types.test.js.map +1 -0
- package/dist/tests/context-packs.test.d.ts +2 -0
- package/dist/tests/context-packs.test.d.ts.map +1 -0
- package/dist/tests/context-packs.test.js +826 -0
- package/dist/tests/context-packs.test.js.map +1 -0
- package/dist/tests/conversational-synthesizer.test.d.ts +2 -0
- package/dist/tests/conversational-synthesizer.test.d.ts.map +1 -0
- package/dist/tests/conversational-synthesizer.test.js +595 -0
- package/dist/tests/conversational-synthesizer.test.js.map +1 -0
- package/dist/tests/database.test.d.ts +2 -0
- package/dist/tests/database.test.d.ts.map +1 -0
- package/dist/tests/database.test.js +965 -0
- package/dist/tests/database.test.js.map +1 -0
- package/dist/tests/encrypted-chunks.test.d.ts +2 -0
- package/dist/tests/encrypted-chunks.test.d.ts.map +1 -0
- package/dist/tests/encrypted-chunks.test.js +1470 -0
- package/dist/tests/encrypted-chunks.test.js.map +1 -0
- package/dist/tests/hybrid.test.d.ts +2 -0
- package/dist/tests/hybrid.test.d.ts.map +1 -0
- package/dist/tests/hybrid.test.js +456 -0
- package/dist/tests/hybrid.test.js.map +1 -0
- package/dist/tests/indexer/ChangeQueue.test.d.ts +12 -0
- package/dist/tests/indexer/ChangeQueue.test.d.ts.map +1 -0
- package/dist/tests/indexer/ChangeQueue.test.js +441 -0
- package/dist/tests/indexer/ChangeQueue.test.js.map +1 -0
- package/dist/tests/indexer/ProviderManager.test.d.ts +12 -0
- package/dist/tests/indexer/ProviderManager.test.d.ts.map +1 -0
- package/dist/tests/indexer/ProviderManager.test.js +290 -0
- package/dist/tests/indexer/ProviderManager.test.js.map +1 -0
- package/dist/tests/indexer/WatchService.test.d.ts +14 -0
- package/dist/tests/indexer/WatchService.test.d.ts.map +1 -0
- package/dist/tests/indexer/WatchService.test.js +667 -0
- package/dist/tests/indexer/WatchService.test.js.map +1 -0
- package/dist/tests/indexer/merkle.test.d.ts +11 -0
- package/dist/tests/indexer/merkle.test.d.ts.map +1 -0
- package/dist/tests/indexer/merkle.test.js +497 -0
- package/dist/tests/indexer/merkle.test.js.map +1 -0
- package/dist/tests/indexer/update.test.d.ts +10 -0
- package/dist/tests/indexer/update.test.d.ts.map +1 -0
- package/dist/tests/indexer/update.test.js +317 -0
- package/dist/tests/indexer/update.test.js.map +1 -0
- package/dist/tests/indexer/watch.test.d.ts +8 -0
- package/dist/tests/indexer/watch.test.d.ts.map +1 -0
- package/dist/tests/indexer/watch.test.js +95 -0
- package/dist/tests/indexer/watch.test.js.map +1 -0
- package/dist/tests/integration/index-search.integration.test.js +6 -4
- package/dist/tests/integration/index-search.integration.test.js.map +1 -1
- package/dist/tests/languages.test.d.ts +2 -0
- package/dist/tests/languages.test.d.ts.map +1 -0
- package/dist/tests/languages.test.js +575 -0
- package/dist/tests/languages.test.js.map +1 -0
- package/dist/tests/logger-redaction.test.d.ts +2 -0
- package/dist/tests/logger-redaction.test.d.ts.map +1 -0
- package/dist/tests/logger-redaction.test.js +48 -0
- package/dist/tests/logger-redaction.test.js.map +1 -0
- package/dist/tests/logger.test.d.ts +2 -0
- package/dist/tests/logger.test.d.ts.map +1 -0
- package/dist/tests/logger.test.js +468 -0
- package/dist/tests/logger.test.js.map +1 -0
- package/dist/tests/markdown-formatter.test.d.ts +2 -0
- package/dist/tests/markdown-formatter.test.d.ts.map +1 -0
- package/dist/tests/markdown-formatter.test.js +453 -0
- package/dist/tests/markdown-formatter.test.js.map +1 -0
- package/dist/tests/mcp/tools/use-context-pack.test.d.ts +7 -0
- package/dist/tests/mcp/tools/use-context-pack.test.d.ts.map +1 -0
- package/dist/tests/mcp/tools/use-context-pack.test.js +505 -0
- package/dist/tests/mcp/tools/use-context-pack.test.js.map +1 -0
- package/dist/tests/mutex.test.d.ts +2 -0
- package/dist/tests/mutex.test.d.ts.map +1 -0
- package/dist/tests/mutex.test.js +489 -0
- package/dist/tests/mutex.test.js.map +1 -0
- package/dist/tests/path-helpers.test.d.ts +2 -0
- package/dist/tests/path-helpers.test.d.ts.map +1 -0
- package/dist/tests/path-helpers.test.js +332 -0
- package/dist/tests/path-helpers.test.js.map +1 -0
- package/dist/tests/prompt-builder.test.d.ts +2 -0
- package/dist/tests/prompt-builder.test.d.ts.map +1 -0
- package/dist/tests/prompt-builder.test.js +417 -0
- package/dist/tests/prompt-builder.test.js.map +1 -0
- package/dist/tests/providers/base.test.d.ts +2 -0
- package/dist/tests/providers/base.test.d.ts.map +1 -0
- package/dist/tests/providers/base.test.js +299 -0
- package/dist/tests/providers/base.test.js.map +1 -0
- package/dist/tests/providers/chat-llm.test.d.ts +2 -0
- package/dist/tests/providers/chat-llm.test.d.ts.map +1 -0
- package/dist/tests/providers/chat-llm.test.js +435 -0
- package/dist/tests/providers/chat-llm.test.js.map +1 -0
- package/dist/tests/providers/index.test.d.ts +2 -0
- package/dist/tests/providers/index.test.d.ts.map +1 -0
- package/dist/tests/providers/index.test.js +204 -0
- package/dist/tests/providers/index.test.js.map +1 -0
- package/dist/tests/providers/mock.test.d.ts +2 -0
- package/dist/tests/providers/mock.test.d.ts.map +1 -0
- package/dist/tests/providers/mock.test.js +225 -0
- package/dist/tests/providers/mock.test.js.map +1 -0
- package/dist/tests/providers/openai.test.d.ts +2 -0
- package/dist/tests/providers/openai.test.d.ts.map +1 -0
- package/dist/tests/providers/openai.test.js +408 -0
- package/dist/tests/providers/openai.test.js.map +1 -0
- package/dist/tests/providers/token-counter.test.d.ts +2 -0
- package/dist/tests/providers/token-counter.test.d.ts.map +1 -0
- package/dist/tests/providers/token-counter.test.js +247 -0
- package/dist/tests/providers/token-counter.test.js.map +1 -0
- package/dist/tests/rate-limiter.test.js +392 -1
- package/dist/tests/rate-limiter.test.js.map +1 -1
- package/dist/tests/scope.test.d.ts +2 -0
- package/dist/tests/scope.test.d.ts.map +1 -0
- package/dist/tests/scope.test.js +529 -0
- package/dist/tests/scope.test.js.map +1 -0
- package/dist/tests/search-normalization.test.js.map +1 -1
- package/dist/tests/semantic-chunker.test.js.map +1 -1
- package/dist/tests/simple-lru.test.js +377 -0
- package/dist/tests/simple-lru.test.js.map +1 -1
- package/dist/tests/symbol-boost.test.js +730 -10
- package/dist/tests/symbol-boost.test.js.map +1 -1
- package/dist/tests/symbols-extract.test.d.ts +2 -0
- package/dist/tests/symbols-extract.test.d.ts.map +1 -0
- package/dist/tests/symbols-extract.test.js +536 -0
- package/dist/tests/symbols-extract.test.js.map +1 -0
- package/dist/tests/symbols-graph.test.d.ts +2 -0
- package/dist/tests/symbols-graph.test.d.ts.map +1 -0
- package/dist/tests/symbols-graph.test.js +656 -0
- package/dist/tests/symbols-graph.test.js.map +1 -0
- package/dist/tests/synthesizer.test.d.ts +2 -0
- package/dist/tests/synthesizer.test.d.ts.map +1 -0
- package/dist/tests/synthesizer.test.js +381 -0
- package/dist/tests/synthesizer.test.js.map +1 -0
- package/dist/types/codemap.d.ts +2 -2
- package/dist/types/codemap.d.ts.map +1 -1
- package/dist/types/codemap.js +17 -9
- package/dist/types/codemap.js.map +1 -1
- package/dist/types/context-pack.d.ts +5 -5
- package/dist/types/context-pack.d.ts.map +1 -1
- package/dist/types/context-pack.js +6 -3
- package/dist/types/context-pack.js.map +1 -1
- package/dist/utils/cli-ui.d.ts +1 -1
- package/dist/utils/cli-ui.d.ts.map +1 -1
- package/dist/utils/cli-ui.js +26 -26
- package/dist/utils/cli-ui.js.map +1 -1
- package/dist/utils/indexer-with-progress.d.ts.map +1 -1
- package/dist/utils/indexer-with-progress.js +0 -6
- package/dist/utils/indexer-with-progress.js.map +1 -1
- package/dist/utils/logger.d.ts +10 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +158 -6
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/mutex.d.ts +7 -2
- package/dist/utils/mutex.d.ts.map +1 -1
- package/dist/utils/mutex.js +35 -7
- package/dist/utils/mutex.js.map +1 -1
- package/dist/utils/path-helpers.d.ts.map +1 -1
- package/dist/utils/path-helpers.js +5 -2
- package/dist/utils/path-helpers.js.map +1 -1
- package/dist/utils/rate-limiter.d.ts.map +1 -1
- package/dist/utils/rate-limiter.js +23 -4
- package/dist/utils/rate-limiter.js.map +1 -1
- package/dist/utils/simple-lru.d.ts +6 -0
- package/dist/utils/simple-lru.d.ts.map +1 -1
- package/dist/utils/simple-lru.js +26 -0
- package/dist/utils/simple-lru.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,992 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import { resolveCodemapPath, readCodemap, writeCodemap, writeCodemapAsync, readCodemapAsync } from '../codemap/io.js';
|
|
7
|
+
import { normalizeChunkMetadata, normalizeCodemapRecord, DEFAULT_PATH_WEIGHT, DEFAULT_SUCCESS_RATE } from '../types/codemap.js';
|
|
8
|
+
import { attachSymbolGraphToCodemap } from '../symbols/graph.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Test Utilities
|
|
11
|
+
// ============================================================================
|
|
12
|
+
function createTempDir() {
|
|
13
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'codemap-test-'));
|
|
14
|
+
}
|
|
15
|
+
function cleanup(tempDir) {
|
|
16
|
+
if (fs.existsSync(tempDir)) {
|
|
17
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// resolveCodemapPath Tests
|
|
22
|
+
// ============================================================================
|
|
23
|
+
test('resolveCodemapPath returns default filename in current directory', () => {
|
|
24
|
+
const result = resolveCodemapPath();
|
|
25
|
+
assert.ok(result.endsWith('codevault.codemap.json'), 'should end with codevault.codemap.json');
|
|
26
|
+
assert.ok(path.isAbsolute(result), 'should return absolute path');
|
|
27
|
+
});
|
|
28
|
+
test('resolveCodemapPath resolves relative to provided basePath', () => {
|
|
29
|
+
const result = resolveCodemapPath('/some/project');
|
|
30
|
+
assert.equal(result, path.resolve('/some/project', 'codevault.codemap.json'));
|
|
31
|
+
});
|
|
32
|
+
test('resolveCodemapPath handles trailing slash in basePath', () => {
|
|
33
|
+
const result = resolveCodemapPath('/some/project/');
|
|
34
|
+
assert.ok(result.includes('codevault.codemap.json'));
|
|
35
|
+
});
|
|
36
|
+
test('resolveCodemapPath handles empty string basePath as current directory', () => {
|
|
37
|
+
const result = resolveCodemapPath('');
|
|
38
|
+
assert.ok(result.endsWith('codevault.codemap.json'));
|
|
39
|
+
});
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// readCodemap Tests (Synchronous)
|
|
42
|
+
// ============================================================================
|
|
43
|
+
test('readCodemap returns empty object when file does not exist', () => {
|
|
44
|
+
const tempDir = createTempDir();
|
|
45
|
+
try {
|
|
46
|
+
const nonExistent = path.join(tempDir, 'nonexistent.json');
|
|
47
|
+
const result = readCodemap(nonExistent);
|
|
48
|
+
assert.deepEqual(result, {});
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
cleanup(tempDir);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
test('readCodemap parses valid JSON file', () => {
|
|
55
|
+
const tempDir = createTempDir();
|
|
56
|
+
try {
|
|
57
|
+
const filePath = path.join(tempDir, 'codemap.json');
|
|
58
|
+
const testData = {
|
|
59
|
+
'chunk1': {
|
|
60
|
+
file: 'src/example.ts',
|
|
61
|
+
sha: 'abc123',
|
|
62
|
+
symbol: 'testFunc',
|
|
63
|
+
lang: 'typescript',
|
|
64
|
+
symbol_neighbors: []
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
fs.writeFileSync(filePath, JSON.stringify(testData));
|
|
68
|
+
const result = readCodemap(filePath);
|
|
69
|
+
assert.equal(result.chunk1.file, 'src/example.ts');
|
|
70
|
+
assert.equal(result.chunk1.sha, 'abc123');
|
|
71
|
+
assert.equal(result.chunk1.symbol, 'testFunc');
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
cleanup(tempDir);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
test('readCodemap returns empty object on malformed JSON', () => {
|
|
78
|
+
const tempDir = createTempDir();
|
|
79
|
+
try {
|
|
80
|
+
const filePath = path.join(tempDir, 'malformed.json');
|
|
81
|
+
fs.writeFileSync(filePath, '{ invalid json }');
|
|
82
|
+
const result = readCodemap(filePath);
|
|
83
|
+
assert.deepEqual(result, {});
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
cleanup(tempDir);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
test('readCodemap normalizes data during read', () => {
|
|
90
|
+
const tempDir = createTempDir();
|
|
91
|
+
try {
|
|
92
|
+
const filePath = path.join(tempDir, 'normalize.json');
|
|
93
|
+
const rawData = {
|
|
94
|
+
'chunk1': {
|
|
95
|
+
file: 'src/test.ts',
|
|
96
|
+
sha: 'xyz789',
|
|
97
|
+
path_weight: -5, // Should be clamped to 0
|
|
98
|
+
success_rate: 2.0, // Should be clamped to 1
|
|
99
|
+
variableCount: 'invalid', // Should default to 0
|
|
100
|
+
synonyms: ['valid', 123] // Non-string should be filtered
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
fs.writeFileSync(filePath, JSON.stringify(rawData));
|
|
104
|
+
const result = readCodemap(filePath);
|
|
105
|
+
assert.equal(result.chunk1.path_weight, 0);
|
|
106
|
+
assert.equal(result.chunk1.success_rate, 1);
|
|
107
|
+
assert.equal(result.chunk1.variableCount, 0);
|
|
108
|
+
assert.deepEqual(result.chunk1.synonyms, ['valid']);
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
cleanup(tempDir);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
test('readCodemap uses default path when no argument provided', () => {
|
|
115
|
+
// This test verifies the function doesn't throw when called without args
|
|
116
|
+
// The file likely won't exist, so we expect empty object
|
|
117
|
+
const result = readCodemap();
|
|
118
|
+
assert.ok(typeof result === 'object');
|
|
119
|
+
});
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// writeCodemap Tests (Synchronous)
|
|
122
|
+
// ============================================================================
|
|
123
|
+
test('writeCodemap creates file with normalized data', () => {
|
|
124
|
+
const tempDir = createTempDir();
|
|
125
|
+
try {
|
|
126
|
+
const filePath = path.join(tempDir, 'output.json');
|
|
127
|
+
const testData = {
|
|
128
|
+
'chunk1': {
|
|
129
|
+
file: 'src/example.ts',
|
|
130
|
+
sha: 'abc123',
|
|
131
|
+
symbol: 'myFunc',
|
|
132
|
+
symbol_neighbors: []
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const result = writeCodemap(filePath, testData);
|
|
136
|
+
assert.ok(fs.existsSync(filePath));
|
|
137
|
+
assert.equal(result.chunk1.file, 'src/example.ts');
|
|
138
|
+
assert.equal(result.chunk1.sha, 'abc123');
|
|
139
|
+
const written = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
140
|
+
assert.equal(written.chunk1.file, 'src/example.ts');
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
cleanup(tempDir);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
test('writeCodemap creates nested directories if needed', () => {
|
|
147
|
+
const tempDir = createTempDir();
|
|
148
|
+
try {
|
|
149
|
+
const nestedPath = path.join(tempDir, 'deep', 'nested', 'dir', 'codemap.json');
|
|
150
|
+
const testData = {
|
|
151
|
+
'chunk1': { file: 'test.ts', sha: 'hash1', symbol_neighbors: [] }
|
|
152
|
+
};
|
|
153
|
+
writeCodemap(nestedPath, testData);
|
|
154
|
+
assert.ok(fs.existsSync(nestedPath));
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
cleanup(tempDir);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
test('writeCodemap overwrites existing file', () => {
|
|
161
|
+
const tempDir = createTempDir();
|
|
162
|
+
try {
|
|
163
|
+
const filePath = path.join(tempDir, 'overwrite.json');
|
|
164
|
+
fs.writeFileSync(filePath, '{"old": "data"}');
|
|
165
|
+
const newData = {
|
|
166
|
+
'new_chunk': { file: 'new.ts', sha: 'newhash', symbol_neighbors: [] }
|
|
167
|
+
};
|
|
168
|
+
writeCodemap(filePath, newData);
|
|
169
|
+
const written = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
170
|
+
assert.ok('new_chunk' in written);
|
|
171
|
+
assert.ok(!('old' in written));
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
cleanup(tempDir);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
test('writeCodemap handles null/undefined codemap gracefully', () => {
|
|
178
|
+
const tempDir = createTempDir();
|
|
179
|
+
try {
|
|
180
|
+
const filePath = path.join(tempDir, 'null.json');
|
|
181
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
182
|
+
const result = writeCodemap(filePath, null);
|
|
183
|
+
assert.deepEqual(result, {});
|
|
184
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
185
|
+
const result2 = writeCodemap(filePath, undefined);
|
|
186
|
+
assert.deepEqual(result2, {});
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
cleanup(tempDir);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
test('writeCodemap uses default path when undefined filePath provided', () => {
|
|
193
|
+
// Note: This will write to current directory, so we need to be careful
|
|
194
|
+
const testData = {
|
|
195
|
+
'chunk1': { file: 'test.ts', sha: 'hash1', symbol_neighbors: [] }
|
|
196
|
+
};
|
|
197
|
+
// The function should not throw
|
|
198
|
+
const result = writeCodemap(undefined, testData);
|
|
199
|
+
assert.ok(typeof result === 'object');
|
|
200
|
+
// Cleanup the file created in current directory
|
|
201
|
+
const defaultPath = resolveCodemapPath('.');
|
|
202
|
+
if (fs.existsSync(defaultPath)) {
|
|
203
|
+
fs.unlinkSync(defaultPath);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
// ============================================================================
|
|
207
|
+
// readCodemapAsync Tests
|
|
208
|
+
// ============================================================================
|
|
209
|
+
test('readCodemapAsync returns empty object when file does not exist', async () => {
|
|
210
|
+
const tempDir = createTempDir();
|
|
211
|
+
try {
|
|
212
|
+
const nonExistent = path.join(tempDir, 'nonexistent.json');
|
|
213
|
+
const result = await readCodemapAsync(nonExistent);
|
|
214
|
+
assert.deepEqual(result, {});
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
cleanup(tempDir);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
test('readCodemapAsync parses valid JSON file', async () => {
|
|
221
|
+
const tempDir = createTempDir();
|
|
222
|
+
try {
|
|
223
|
+
const filePath = path.join(tempDir, 'async-read.json');
|
|
224
|
+
const testData = {
|
|
225
|
+
'async_chunk': {
|
|
226
|
+
file: 'async.ts',
|
|
227
|
+
sha: 'asynchash',
|
|
228
|
+
symbol: 'asyncFunc',
|
|
229
|
+
symbol_neighbors: []
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
fs.writeFileSync(filePath, JSON.stringify(testData));
|
|
233
|
+
const result = await readCodemapAsync(filePath);
|
|
234
|
+
assert.equal(result.async_chunk.file, 'async.ts');
|
|
235
|
+
assert.equal(result.async_chunk.symbol, 'asyncFunc');
|
|
236
|
+
}
|
|
237
|
+
finally {
|
|
238
|
+
cleanup(tempDir);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
test('readCodemapAsync returns empty object on malformed JSON', async () => {
|
|
242
|
+
const tempDir = createTempDir();
|
|
243
|
+
try {
|
|
244
|
+
const filePath = path.join(tempDir, 'async-malformed.json');
|
|
245
|
+
fs.writeFileSync(filePath, 'not valid json {{{');
|
|
246
|
+
const result = await readCodemapAsync(filePath);
|
|
247
|
+
assert.deepEqual(result, {});
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
cleanup(tempDir);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
test('readCodemapAsync normalizes data during read', async () => {
|
|
254
|
+
const tempDir = createTempDir();
|
|
255
|
+
try {
|
|
256
|
+
const filePath = path.join(tempDir, 'async-normalize.json');
|
|
257
|
+
const rawData = {
|
|
258
|
+
'chunk1': {
|
|
259
|
+
file: 'test.ts',
|
|
260
|
+
sha: 'hash',
|
|
261
|
+
success_rate: -0.5 // Should be clamped to 0
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
fs.writeFileSync(filePath, JSON.stringify(rawData));
|
|
265
|
+
const result = await readCodemapAsync(filePath);
|
|
266
|
+
assert.equal(result.chunk1.success_rate, 0);
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
cleanup(tempDir);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
// ============================================================================
|
|
273
|
+
// writeCodemapAsync Tests
|
|
274
|
+
// ============================================================================
|
|
275
|
+
test('writeCodemapAsync creates file with normalized data', async () => {
|
|
276
|
+
const tempDir = createTempDir();
|
|
277
|
+
try {
|
|
278
|
+
const filePath = path.join(tempDir, 'async-write.json');
|
|
279
|
+
const testData = {
|
|
280
|
+
'async_chunk': {
|
|
281
|
+
file: 'async.ts',
|
|
282
|
+
sha: 'asynchash',
|
|
283
|
+
symbol: 'myAsyncFunc',
|
|
284
|
+
symbol_neighbors: []
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
const result = await writeCodemapAsync(filePath, testData);
|
|
288
|
+
assert.ok(fs.existsSync(filePath));
|
|
289
|
+
assert.equal(result.async_chunk.file, 'async.ts');
|
|
290
|
+
}
|
|
291
|
+
finally {
|
|
292
|
+
cleanup(tempDir);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
test('writeCodemapAsync creates nested directories', async () => {
|
|
296
|
+
const tempDir = createTempDir();
|
|
297
|
+
try {
|
|
298
|
+
const nestedPath = path.join(tempDir, 'async', 'nested', 'path', 'codemap.json');
|
|
299
|
+
const testData = {
|
|
300
|
+
'chunk1': { file: 'test.ts', sha: 'hash1', symbol_neighbors: [] }
|
|
301
|
+
};
|
|
302
|
+
await writeCodemapAsync(nestedPath, testData);
|
|
303
|
+
assert.ok(fs.existsSync(nestedPath));
|
|
304
|
+
}
|
|
305
|
+
finally {
|
|
306
|
+
cleanup(tempDir);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
test('writeCodemapAsync handles null codemap', async () => {
|
|
310
|
+
const tempDir = createTempDir();
|
|
311
|
+
try {
|
|
312
|
+
const filePath = path.join(tempDir, 'async-null.json');
|
|
313
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
314
|
+
const result = await writeCodemapAsync(filePath, null);
|
|
315
|
+
assert.deepEqual(result, {});
|
|
316
|
+
}
|
|
317
|
+
finally {
|
|
318
|
+
cleanup(tempDir);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
// ============================================================================
|
|
322
|
+
// normalizeChunkMetadata Tests
|
|
323
|
+
// ============================================================================
|
|
324
|
+
test('normalizeChunkMetadata handles minimal valid input', () => {
|
|
325
|
+
const raw = {
|
|
326
|
+
file: 'test.ts',
|
|
327
|
+
sha: 'abc123'
|
|
328
|
+
};
|
|
329
|
+
const result = normalizeChunkMetadata(raw);
|
|
330
|
+
assert.equal(result.file, 'test.ts');
|
|
331
|
+
assert.equal(result.sha, 'abc123');
|
|
332
|
+
assert.equal(result.lang, 'unknown');
|
|
333
|
+
assert.equal(result.symbol, null);
|
|
334
|
+
assert.equal(result.path_weight, DEFAULT_PATH_WEIGHT);
|
|
335
|
+
assert.equal(result.success_rate, DEFAULT_SUCCESS_RATE);
|
|
336
|
+
assert.equal(result.encrypted, false);
|
|
337
|
+
assert.deepEqual(result.symbol_neighbors, []);
|
|
338
|
+
});
|
|
339
|
+
test('normalizeChunkMetadata handles empty/invalid file and sha', () => {
|
|
340
|
+
const raw = {
|
|
341
|
+
file: '',
|
|
342
|
+
sha: null
|
|
343
|
+
};
|
|
344
|
+
const result = normalizeChunkMetadata(raw);
|
|
345
|
+
assert.equal(result.file, 'unknown');
|
|
346
|
+
assert.equal(result.sha, 'unknown');
|
|
347
|
+
});
|
|
348
|
+
test('normalizeChunkMetadata clamps path_weight to non-negative', () => {
|
|
349
|
+
const result1 = normalizeChunkMetadata({ file: 'a', sha: 'b', path_weight: -10 });
|
|
350
|
+
assert.equal(result1.path_weight, 0);
|
|
351
|
+
const result2 = normalizeChunkMetadata({ file: 'a', sha: 'b', path_weight: 5.5 });
|
|
352
|
+
assert.equal(result2.path_weight, 5.5);
|
|
353
|
+
});
|
|
354
|
+
test('normalizeChunkMetadata clamps success_rate to 0-1 range', () => {
|
|
355
|
+
const result1 = normalizeChunkMetadata({ file: 'a', sha: 'b', success_rate: -0.5 });
|
|
356
|
+
assert.equal(result1.success_rate, 0);
|
|
357
|
+
const result2 = normalizeChunkMetadata({ file: 'a', sha: 'b', success_rate: 2.0 });
|
|
358
|
+
assert.equal(result2.success_rate, 1);
|
|
359
|
+
const result3 = normalizeChunkMetadata({ file: 'a', sha: 'b', success_rate: 0.75 });
|
|
360
|
+
assert.equal(result3.success_rate, 0.75);
|
|
361
|
+
});
|
|
362
|
+
test('normalizeChunkMetadata handles NaN success_rate', () => {
|
|
363
|
+
const result = normalizeChunkMetadata({ file: 'a', sha: 'b', success_rate: NaN });
|
|
364
|
+
assert.equal(result.success_rate, DEFAULT_SUCCESS_RATE);
|
|
365
|
+
});
|
|
366
|
+
test('normalizeChunkMetadata sanitizes variableCount', () => {
|
|
367
|
+
const result1 = normalizeChunkMetadata({ file: 'a', sha: 'b', variableCount: -5 });
|
|
368
|
+
assert.equal(result1.variableCount, 0);
|
|
369
|
+
const result2 = normalizeChunkMetadata({ file: 'a', sha: 'b', variableCount: 3.7 });
|
|
370
|
+
assert.equal(result2.variableCount, 4);
|
|
371
|
+
const result3 = normalizeChunkMetadata({ file: 'a', sha: 'b', variableCount: 'invalid' });
|
|
372
|
+
assert.equal(result3.variableCount, 0);
|
|
373
|
+
const result4 = normalizeChunkMetadata({ file: 'a', sha: 'b', variableCount: Infinity });
|
|
374
|
+
assert.equal(result4.variableCount, 0);
|
|
375
|
+
});
|
|
376
|
+
test('normalizeChunkMetadata sanitizes string arrays (synonyms, symbol_calls, etc.)', () => {
|
|
377
|
+
const raw = {
|
|
378
|
+
file: 'test.ts',
|
|
379
|
+
sha: 'hash',
|
|
380
|
+
synonyms: ['valid', 123, null, '', ' trimmed ', 'duplicate', 'duplicate'],
|
|
381
|
+
symbol_calls: ['funcA', 'funcB', 42],
|
|
382
|
+
symbol_parameters: ['param1', 'param2']
|
|
383
|
+
};
|
|
384
|
+
const result = normalizeChunkMetadata(raw);
|
|
385
|
+
assert.deepEqual(result.synonyms, ['valid', 'trimmed', 'duplicate']);
|
|
386
|
+
assert.deepEqual(result.symbol_calls, ['funcA', 'funcB']);
|
|
387
|
+
assert.deepEqual(result.symbol_parameters, ['param1', 'param2']);
|
|
388
|
+
});
|
|
389
|
+
test('normalizeChunkMetadata handles symbol_neighbors deduplication', () => {
|
|
390
|
+
const raw = {
|
|
391
|
+
file: 'test.ts',
|
|
392
|
+
sha: 'hash',
|
|
393
|
+
symbol_neighbors: ['neighbor1', 'neighbor1', 'neighbor2', ' neighbor3 ']
|
|
394
|
+
};
|
|
395
|
+
const result = normalizeChunkMetadata(raw);
|
|
396
|
+
assert.deepEqual(result.symbol_neighbors, ['neighbor1', 'neighbor2', 'neighbor3']);
|
|
397
|
+
});
|
|
398
|
+
test('normalizeChunkMetadata handles last_used_at date parsing', () => {
|
|
399
|
+
const validDate = '2024-01-15T10:30:00.000Z';
|
|
400
|
+
const result1 = normalizeChunkMetadata({ file: 'a', sha: 'b', last_used_at: validDate });
|
|
401
|
+
assert.equal(result1.last_used_at, validDate);
|
|
402
|
+
const result2 = normalizeChunkMetadata({ file: 'a', sha: 'b', last_used_at: 'invalid-date' });
|
|
403
|
+
assert.equal(result2.last_used_at, undefined);
|
|
404
|
+
const result3 = normalizeChunkMetadata({ file: 'a', sha: 'b', last_used_at: null });
|
|
405
|
+
assert.equal(result3.last_used_at, undefined);
|
|
406
|
+
});
|
|
407
|
+
test('normalizeChunkMetadata handles symbol_signature', () => {
|
|
408
|
+
const result1 = normalizeChunkMetadata({ file: 'a', sha: 'b', symbol_signature: 'myFunc(a, b)' });
|
|
409
|
+
assert.equal(result1.symbol_signature, 'myFunc(a, b)');
|
|
410
|
+
const result2 = normalizeChunkMetadata({ file: 'a', sha: 'b', symbol_signature: ' ' });
|
|
411
|
+
assert.equal(result2.symbol_signature, undefined);
|
|
412
|
+
const result3 = normalizeChunkMetadata({ file: 'a', sha: 'b', symbol_signature: 123 });
|
|
413
|
+
assert.equal(result3.symbol_signature, undefined);
|
|
414
|
+
});
|
|
415
|
+
test('normalizeChunkMetadata handles symbol_return', () => {
|
|
416
|
+
const result1 = normalizeChunkMetadata({ file: 'a', sha: 'b', symbol_return: 'Promise<void>' });
|
|
417
|
+
assert.equal(result1.symbol_return, 'Promise<void>');
|
|
418
|
+
const result2 = normalizeChunkMetadata({ file: 'a', sha: 'b', symbol_return: '' });
|
|
419
|
+
assert.equal(result2.symbol_return, undefined);
|
|
420
|
+
});
|
|
421
|
+
test('normalizeChunkMetadata preserves boolean fields', () => {
|
|
422
|
+
const raw = {
|
|
423
|
+
file: 'test.ts',
|
|
424
|
+
sha: 'hash',
|
|
425
|
+
hasCodevaultTags: true,
|
|
426
|
+
hasIntent: true,
|
|
427
|
+
hasDocumentation: true,
|
|
428
|
+
encrypted: true
|
|
429
|
+
};
|
|
430
|
+
const result = normalizeChunkMetadata(raw);
|
|
431
|
+
assert.equal(result.hasCodevaultTags, true);
|
|
432
|
+
assert.equal(result.hasIntent, true);
|
|
433
|
+
assert.equal(result.hasDocumentation, true);
|
|
434
|
+
assert.equal(result.encrypted, true);
|
|
435
|
+
});
|
|
436
|
+
test('normalizeChunkMetadata defaults boolean fields to false', () => {
|
|
437
|
+
const result = normalizeChunkMetadata({ file: 'a', sha: 'b' });
|
|
438
|
+
assert.equal(result.hasCodevaultTags, false);
|
|
439
|
+
assert.equal(result.hasIntent, false);
|
|
440
|
+
assert.equal(result.hasDocumentation, false);
|
|
441
|
+
assert.equal(result.encrypted, false);
|
|
442
|
+
});
|
|
443
|
+
test('normalizeChunkMetadata handles provider and dimensions', () => {
|
|
444
|
+
const result1 = normalizeChunkMetadata({
|
|
445
|
+
file: 'a',
|
|
446
|
+
sha: 'b',
|
|
447
|
+
provider: 'openai',
|
|
448
|
+
dimensions: 1536
|
|
449
|
+
});
|
|
450
|
+
assert.equal(result1.provider, 'openai');
|
|
451
|
+
assert.equal(result1.dimensions, 1536);
|
|
452
|
+
const result2 = normalizeChunkMetadata({
|
|
453
|
+
file: 'a',
|
|
454
|
+
sha: 'b',
|
|
455
|
+
provider: '',
|
|
456
|
+
dimensions: NaN
|
|
457
|
+
});
|
|
458
|
+
assert.equal(result2.provider, undefined);
|
|
459
|
+
assert.equal(result2.dimensions, undefined);
|
|
460
|
+
});
|
|
461
|
+
test('normalizeChunkMetadata preserves extra fields (passthrough)', () => {
|
|
462
|
+
const raw = {
|
|
463
|
+
file: 'test.ts',
|
|
464
|
+
sha: 'hash',
|
|
465
|
+
customField: 'customValue',
|
|
466
|
+
anotherCustom: 42
|
|
467
|
+
};
|
|
468
|
+
const result = normalizeChunkMetadata(raw);
|
|
469
|
+
assert.equal(result.customField, 'customValue');
|
|
470
|
+
assert.equal(result.anotherCustom, 42);
|
|
471
|
+
});
|
|
472
|
+
test('normalizeChunkMetadata merges with previous chunk data', () => {
|
|
473
|
+
const previous = {
|
|
474
|
+
file: 'old.ts',
|
|
475
|
+
sha: 'oldhash',
|
|
476
|
+
symbol: 'oldSymbol',
|
|
477
|
+
lang: 'typescript',
|
|
478
|
+
path_weight: 2.0,
|
|
479
|
+
success_rate: 0.8,
|
|
480
|
+
symbol_neighbors: ['neighbor1']
|
|
481
|
+
};
|
|
482
|
+
const incoming = {
|
|
483
|
+
sha: 'newhash',
|
|
484
|
+
symbol: 'newSymbol'
|
|
485
|
+
};
|
|
486
|
+
const result = normalizeChunkMetadata(incoming, previous);
|
|
487
|
+
assert.equal(result.file, 'old.ts'); // From previous
|
|
488
|
+
assert.equal(result.sha, 'newhash'); // Overwritten
|
|
489
|
+
assert.equal(result.symbol, 'newSymbol'); // Overwritten
|
|
490
|
+
assert.equal(result.lang, 'typescript'); // From previous
|
|
491
|
+
assert.equal(result.path_weight, 2.0); // From previous
|
|
492
|
+
});
|
|
493
|
+
test('normalizeChunkMetadata handles null/undefined input', () => {
|
|
494
|
+
const result1 = normalizeChunkMetadata(null);
|
|
495
|
+
assert.equal(result1.file, 'unknown');
|
|
496
|
+
assert.equal(result1.sha, 'unknown');
|
|
497
|
+
const result2 = normalizeChunkMetadata(undefined);
|
|
498
|
+
assert.equal(result2.file, 'unknown');
|
|
499
|
+
assert.equal(result2.sha, 'unknown');
|
|
500
|
+
});
|
|
501
|
+
// ============================================================================
|
|
502
|
+
// normalizeCodemapRecord Tests
|
|
503
|
+
// ============================================================================
|
|
504
|
+
test('normalizeCodemapRecord handles empty input', () => {
|
|
505
|
+
assert.deepEqual(normalizeCodemapRecord(null), {});
|
|
506
|
+
assert.deepEqual(normalizeCodemapRecord(undefined), {});
|
|
507
|
+
assert.deepEqual(normalizeCodemapRecord({}), {});
|
|
508
|
+
assert.deepEqual(normalizeCodemapRecord('string'), {});
|
|
509
|
+
assert.deepEqual(normalizeCodemapRecord(123), {});
|
|
510
|
+
});
|
|
511
|
+
test('normalizeCodemapRecord normalizes all chunks', () => {
|
|
512
|
+
const raw = {
|
|
513
|
+
'chunk1': { file: 'a.ts', sha: 'hash1', path_weight: -1 },
|
|
514
|
+
'chunk2': { file: 'b.ts', sha: 'hash2', success_rate: 5 }
|
|
515
|
+
};
|
|
516
|
+
const result = normalizeCodemapRecord(raw);
|
|
517
|
+
assert.equal(result.chunk1.path_weight, 0);
|
|
518
|
+
assert.equal(result.chunk2.success_rate, 1);
|
|
519
|
+
});
|
|
520
|
+
test('normalizeCodemapRecord sorts chunks alphabetically by key', () => {
|
|
521
|
+
const raw = {
|
|
522
|
+
'z_chunk': { file: 'z.ts', sha: 'z' },
|
|
523
|
+
'a_chunk': { file: 'a.ts', sha: 'a' },
|
|
524
|
+
'm_chunk': { file: 'm.ts', sha: 'm' }
|
|
525
|
+
};
|
|
526
|
+
const result = normalizeCodemapRecord(raw);
|
|
527
|
+
const keys = Object.keys(result);
|
|
528
|
+
assert.deepEqual(keys, ['a_chunk', 'm_chunk', 'z_chunk']);
|
|
529
|
+
});
|
|
530
|
+
test('normalizeCodemapRecord filters out empty string keys', () => {
|
|
531
|
+
const raw = {
|
|
532
|
+
'': { file: 'empty.ts', sha: 'empty' },
|
|
533
|
+
'valid': { file: 'valid.ts', sha: 'valid' }
|
|
534
|
+
};
|
|
535
|
+
const result = normalizeCodemapRecord(raw);
|
|
536
|
+
assert.ok(!('' in result));
|
|
537
|
+
assert.ok('valid' in result);
|
|
538
|
+
});
|
|
539
|
+
// ============================================================================
|
|
540
|
+
// attachSymbolGraphToCodemap Tests
|
|
541
|
+
// ============================================================================
|
|
542
|
+
test('attachSymbolGraphToCodemap handles null/undefined input', () => {
|
|
543
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
544
|
+
assert.equal(attachSymbolGraphToCodemap(null), null);
|
|
545
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
546
|
+
assert.equal(attachSymbolGraphToCodemap(undefined), undefined);
|
|
547
|
+
});
|
|
548
|
+
test('attachSymbolGraphToCodemap handles empty codemap', () => {
|
|
549
|
+
const result = attachSymbolGraphToCodemap({});
|
|
550
|
+
assert.deepEqual(result, {});
|
|
551
|
+
});
|
|
552
|
+
test('attachSymbolGraphToCodemap builds call targets from symbol_calls', () => {
|
|
553
|
+
const codemap = {
|
|
554
|
+
'chunk1': {
|
|
555
|
+
file: 'src/main.ts',
|
|
556
|
+
sha: 'sha1',
|
|
557
|
+
symbol: 'main',
|
|
558
|
+
symbol_calls: ['helper'],
|
|
559
|
+
symbol_neighbors: []
|
|
560
|
+
},
|
|
561
|
+
'chunk2': {
|
|
562
|
+
file: 'src/utils.ts',
|
|
563
|
+
sha: 'sha2',
|
|
564
|
+
symbol: 'helper',
|
|
565
|
+
symbol_calls: [],
|
|
566
|
+
symbol_neighbors: []
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
570
|
+
// chunk1 calls helper (chunk2)
|
|
571
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, ['sha2']);
|
|
572
|
+
// chunk2 is called by chunk1
|
|
573
|
+
assert.deepEqual(result.chunk2.symbol_callers, ['sha1']);
|
|
574
|
+
// Both should have neighbors
|
|
575
|
+
assert.ok(result.chunk1.symbol_neighbors?.includes('sha2'));
|
|
576
|
+
assert.ok(result.chunk2.symbol_neighbors?.includes('sha1'));
|
|
577
|
+
});
|
|
578
|
+
test('attachSymbolGraphToCodemap handles case-insensitive symbol matching', () => {
|
|
579
|
+
const codemap = {
|
|
580
|
+
'chunk1': {
|
|
581
|
+
file: 'main.ts',
|
|
582
|
+
sha: 'sha1',
|
|
583
|
+
symbol: 'caller',
|
|
584
|
+
symbol_calls: ['ProcessData'], // Mixed case call
|
|
585
|
+
symbol_neighbors: []
|
|
586
|
+
},
|
|
587
|
+
'chunk2': {
|
|
588
|
+
file: 'utils.ts',
|
|
589
|
+
sha: 'sha2',
|
|
590
|
+
symbol: 'processData', // camelCase definition
|
|
591
|
+
symbol_calls: [],
|
|
592
|
+
symbol_neighbors: []
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
596
|
+
// Should match despite case difference
|
|
597
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, ['sha2']);
|
|
598
|
+
});
|
|
599
|
+
test('attachSymbolGraphToCodemap prefers same-file candidates', () => {
|
|
600
|
+
const codemap = {
|
|
601
|
+
'chunk1': {
|
|
602
|
+
file: 'src/main.ts',
|
|
603
|
+
sha: 'sha1',
|
|
604
|
+
symbol: 'caller',
|
|
605
|
+
symbol_calls: ['helper'],
|
|
606
|
+
symbol_neighbors: []
|
|
607
|
+
},
|
|
608
|
+
'chunk2': {
|
|
609
|
+
file: 'src/main.ts', // Same file as caller
|
|
610
|
+
sha: 'sha2',
|
|
611
|
+
symbol: 'helper',
|
|
612
|
+
symbol_calls: [],
|
|
613
|
+
symbol_neighbors: []
|
|
614
|
+
},
|
|
615
|
+
'chunk3': {
|
|
616
|
+
file: 'src/other.ts', // Different file
|
|
617
|
+
sha: 'sha3',
|
|
618
|
+
symbol: 'helper', // Same symbol name
|
|
619
|
+
symbol_calls: [],
|
|
620
|
+
symbol_neighbors: []
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
624
|
+
// Should prefer chunk2 (same file) over chunk3
|
|
625
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, ['sha2']);
|
|
626
|
+
});
|
|
627
|
+
test('attachSymbolGraphToCodemap ignores self-references', () => {
|
|
628
|
+
const codemap = {
|
|
629
|
+
'chunk1': {
|
|
630
|
+
file: 'main.ts',
|
|
631
|
+
sha: 'sha1',
|
|
632
|
+
symbol: 'recursive',
|
|
633
|
+
symbol_calls: ['recursive'], // Calls itself
|
|
634
|
+
symbol_neighbors: []
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
638
|
+
// Should not include self-reference
|
|
639
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, []);
|
|
640
|
+
assert.deepEqual(result.chunk1.symbol_callers, []);
|
|
641
|
+
});
|
|
642
|
+
test('attachSymbolGraphToCodemap handles chunks without symbols', () => {
|
|
643
|
+
const codemap = {
|
|
644
|
+
'chunk1': {
|
|
645
|
+
file: 'main.ts',
|
|
646
|
+
sha: 'sha1',
|
|
647
|
+
symbol: null,
|
|
648
|
+
symbol_calls: ['helper'],
|
|
649
|
+
symbol_neighbors: []
|
|
650
|
+
},
|
|
651
|
+
'chunk2': {
|
|
652
|
+
file: 'utils.ts',
|
|
653
|
+
sha: 'sha2',
|
|
654
|
+
symbol: 'helper',
|
|
655
|
+
symbol_calls: [],
|
|
656
|
+
symbol_neighbors: []
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
660
|
+
// chunk1 can still call chunk2
|
|
661
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, ['sha2']);
|
|
662
|
+
});
|
|
663
|
+
test('attachSymbolGraphToCodemap handles missing symbol_calls array', () => {
|
|
664
|
+
const codemap = {
|
|
665
|
+
'chunk1': {
|
|
666
|
+
file: 'main.ts',
|
|
667
|
+
sha: 'sha1',
|
|
668
|
+
symbol: 'main',
|
|
669
|
+
symbol_neighbors: []
|
|
670
|
+
// symbol_calls is missing
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
674
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, []);
|
|
675
|
+
assert.deepEqual(result.chunk1.symbol_callers, []);
|
|
676
|
+
});
|
|
677
|
+
test('attachSymbolGraphToCodemap handles complex call graph', () => {
|
|
678
|
+
const codemap = {
|
|
679
|
+
'a': {
|
|
680
|
+
file: 'a.ts',
|
|
681
|
+
sha: 'sha_a',
|
|
682
|
+
symbol: 'funcA',
|
|
683
|
+
symbol_calls: ['funcB', 'funcC'],
|
|
684
|
+
symbol_neighbors: []
|
|
685
|
+
},
|
|
686
|
+
'b': {
|
|
687
|
+
file: 'b.ts',
|
|
688
|
+
sha: 'sha_b',
|
|
689
|
+
symbol: 'funcB',
|
|
690
|
+
symbol_calls: ['funcC'],
|
|
691
|
+
symbol_neighbors: []
|
|
692
|
+
},
|
|
693
|
+
'c': {
|
|
694
|
+
file: 'c.ts',
|
|
695
|
+
sha: 'sha_c',
|
|
696
|
+
symbol: 'funcC',
|
|
697
|
+
symbol_calls: [],
|
|
698
|
+
symbol_neighbors: []
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
702
|
+
// A calls B and C
|
|
703
|
+
assert.ok(result.a.symbol_call_targets?.includes('sha_b'));
|
|
704
|
+
assert.ok(result.a.symbol_call_targets?.includes('sha_c'));
|
|
705
|
+
// B calls C
|
|
706
|
+
assert.deepEqual(result.b.symbol_call_targets, ['sha_c']);
|
|
707
|
+
// C is called by A and B
|
|
708
|
+
assert.ok(result.c.symbol_callers?.includes('sha_a'));
|
|
709
|
+
assert.ok(result.c.symbol_callers?.includes('sha_b'));
|
|
710
|
+
// Neighbors include both incoming and outgoing
|
|
711
|
+
assert.ok(result.c.symbol_neighbors?.includes('sha_a'));
|
|
712
|
+
assert.ok(result.c.symbol_neighbors?.includes('sha_b'));
|
|
713
|
+
});
|
|
714
|
+
test('attachSymbolGraphToCodemap ignores empty symbol calls', () => {
|
|
715
|
+
const codemap = {
|
|
716
|
+
'chunk1': {
|
|
717
|
+
file: 'main.ts',
|
|
718
|
+
sha: 'sha1',
|
|
719
|
+
symbol: 'main',
|
|
720
|
+
symbol_calls: ['', ' ', 'validCall'],
|
|
721
|
+
symbol_neighbors: []
|
|
722
|
+
},
|
|
723
|
+
'chunk2': {
|
|
724
|
+
file: 'utils.ts',
|
|
725
|
+
sha: 'sha2',
|
|
726
|
+
symbol: 'validCall',
|
|
727
|
+
symbol_calls: [],
|
|
728
|
+
symbol_neighbors: []
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
732
|
+
// Should only resolve the valid call
|
|
733
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, ['sha2']);
|
|
734
|
+
});
|
|
735
|
+
test('attachSymbolGraphToCodemap handles unresolved calls gracefully', () => {
|
|
736
|
+
const codemap = {
|
|
737
|
+
'chunk1': {
|
|
738
|
+
file: 'main.ts',
|
|
739
|
+
sha: 'sha1',
|
|
740
|
+
symbol: 'main',
|
|
741
|
+
symbol_calls: ['nonExistentFunc', 'anotherMissing'],
|
|
742
|
+
symbol_neighbors: []
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
746
|
+
// Unresolved calls should result in empty arrays
|
|
747
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, []);
|
|
748
|
+
assert.deepEqual(result.chunk1.symbol_callers, []);
|
|
749
|
+
assert.deepEqual(result.chunk1.symbol_neighbors, []);
|
|
750
|
+
});
|
|
751
|
+
// ============================================================================
|
|
752
|
+
// Round-trip Tests (Serialization/Deserialization)
|
|
753
|
+
// ============================================================================
|
|
754
|
+
test('round-trip: write and read codemap preserves data', async () => {
|
|
755
|
+
const tempDir = createTempDir();
|
|
756
|
+
try {
|
|
757
|
+
const filePath = path.join(tempDir, 'roundtrip.json');
|
|
758
|
+
const original = {
|
|
759
|
+
'chunk1': {
|
|
760
|
+
file: 'src/main.ts',
|
|
761
|
+
sha: 'abc123def456',
|
|
762
|
+
symbol: 'processData',
|
|
763
|
+
lang: 'typescript',
|
|
764
|
+
chunkType: 'function',
|
|
765
|
+
provider: 'openai',
|
|
766
|
+
dimensions: 1536,
|
|
767
|
+
hasCodevaultTags: true,
|
|
768
|
+
hasIntent: false,
|
|
769
|
+
hasDocumentation: true,
|
|
770
|
+
variableCount: 5,
|
|
771
|
+
synonyms: ['process', 'handle', 'transform'],
|
|
772
|
+
path_weight: 1.5,
|
|
773
|
+
success_rate: 0.85,
|
|
774
|
+
encrypted: false,
|
|
775
|
+
symbol_signature: 'processData(input: string): Promise<Result>',
|
|
776
|
+
symbol_parameters: ['input'],
|
|
777
|
+
symbol_return: 'Promise<Result>',
|
|
778
|
+
symbol_calls: ['validate', 'transform', 'save'],
|
|
779
|
+
symbol_call_targets: ['sha_validate', 'sha_transform', 'sha_save'],
|
|
780
|
+
symbol_callers: ['sha_main'],
|
|
781
|
+
symbol_neighbors: ['sha_validate', 'sha_transform', 'sha_save', 'sha_main']
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
writeCodemap(filePath, original);
|
|
785
|
+
const loaded = readCodemap(filePath);
|
|
786
|
+
assert.equal(loaded.chunk1.file, original.chunk1.file);
|
|
787
|
+
assert.equal(loaded.chunk1.sha, original.chunk1.sha);
|
|
788
|
+
assert.equal(loaded.chunk1.symbol, original.chunk1.symbol);
|
|
789
|
+
assert.equal(loaded.chunk1.lang, original.chunk1.lang);
|
|
790
|
+
assert.equal(loaded.chunk1.provider, original.chunk1.provider);
|
|
791
|
+
assert.equal(loaded.chunk1.dimensions, original.chunk1.dimensions);
|
|
792
|
+
assert.equal(loaded.chunk1.path_weight, original.chunk1.path_weight);
|
|
793
|
+
assert.equal(loaded.chunk1.success_rate, original.chunk1.success_rate);
|
|
794
|
+
assert.deepEqual(loaded.chunk1.synonyms, original.chunk1.synonyms);
|
|
795
|
+
assert.deepEqual(loaded.chunk1.symbol_parameters, original.chunk1.symbol_parameters);
|
|
796
|
+
assert.deepEqual(loaded.chunk1.symbol_calls, original.chunk1.symbol_calls);
|
|
797
|
+
}
|
|
798
|
+
finally {
|
|
799
|
+
cleanup(tempDir);
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
test('round-trip async: write and read codemap preserves data', async () => {
|
|
803
|
+
const tempDir = createTempDir();
|
|
804
|
+
try {
|
|
805
|
+
const filePath = path.join(tempDir, 'roundtrip-async.json');
|
|
806
|
+
const original = {
|
|
807
|
+
'async_chunk': {
|
|
808
|
+
file: 'async.ts',
|
|
809
|
+
sha: 'asynchash123',
|
|
810
|
+
symbol: 'asyncFunc',
|
|
811
|
+
symbol_neighbors: ['neighbor1', 'neighbor2']
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
await writeCodemapAsync(filePath, original);
|
|
815
|
+
const loaded = await readCodemapAsync(filePath);
|
|
816
|
+
assert.equal(loaded.async_chunk.file, original.async_chunk.file);
|
|
817
|
+
assert.equal(loaded.async_chunk.sha, original.async_chunk.sha);
|
|
818
|
+
assert.deepEqual(loaded.async_chunk.symbol_neighbors, original.async_chunk.symbol_neighbors);
|
|
819
|
+
}
|
|
820
|
+
finally {
|
|
821
|
+
cleanup(tempDir);
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
// ============================================================================
|
|
825
|
+
// Cross-file Reference Tests
|
|
826
|
+
// ============================================================================
|
|
827
|
+
test('cross-file references: complete workflow', () => {
|
|
828
|
+
const codemap = {
|
|
829
|
+
'user_service': {
|
|
830
|
+
file: 'src/services/user.ts',
|
|
831
|
+
sha: 'sha_user',
|
|
832
|
+
symbol: 'UserService',
|
|
833
|
+
symbol_calls: ['validateUser', 'saveToDatabase', 'sendNotification'],
|
|
834
|
+
symbol_neighbors: []
|
|
835
|
+
},
|
|
836
|
+
'validator': {
|
|
837
|
+
file: 'src/utils/validator.ts',
|
|
838
|
+
sha: 'sha_validator',
|
|
839
|
+
symbol: 'validateUser',
|
|
840
|
+
symbol_calls: [],
|
|
841
|
+
symbol_neighbors: []
|
|
842
|
+
},
|
|
843
|
+
'database': {
|
|
844
|
+
file: 'src/database/db.ts',
|
|
845
|
+
sha: 'sha_db',
|
|
846
|
+
symbol: 'saveToDatabase',
|
|
847
|
+
symbol_calls: ['connect', 'query'],
|
|
848
|
+
symbol_neighbors: []
|
|
849
|
+
},
|
|
850
|
+
'notifier': {
|
|
851
|
+
file: 'src/services/notification.ts',
|
|
852
|
+
sha: 'sha_notifier',
|
|
853
|
+
symbol: 'sendNotification',
|
|
854
|
+
symbol_calls: ['validateUser'], // Also calls validator
|
|
855
|
+
symbol_neighbors: []
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
859
|
+
// UserService should call all three
|
|
860
|
+
assert.ok(result.user_service.symbol_call_targets?.includes('sha_validator'));
|
|
861
|
+
assert.ok(result.user_service.symbol_call_targets?.includes('sha_db'));
|
|
862
|
+
assert.ok(result.user_service.symbol_call_targets?.includes('sha_notifier'));
|
|
863
|
+
// Validator is called by UserService and Notifier
|
|
864
|
+
assert.ok(result.validator.symbol_callers?.includes('sha_user'));
|
|
865
|
+
assert.ok(result.validator.symbol_callers?.includes('sha_notifier'));
|
|
866
|
+
// Validator's neighbors should include both callers
|
|
867
|
+
assert.ok(result.validator.symbol_neighbors?.includes('sha_user'));
|
|
868
|
+
assert.ok(result.validator.symbol_neighbors?.includes('sha_notifier'));
|
|
869
|
+
});
|
|
870
|
+
test('cross-file references: bidirectional relationships', () => {
|
|
871
|
+
const codemap = {
|
|
872
|
+
'module_a': {
|
|
873
|
+
file: 'a.ts',
|
|
874
|
+
sha: 'sha_a',
|
|
875
|
+
symbol: 'moduleA',
|
|
876
|
+
symbol_calls: ['moduleB'],
|
|
877
|
+
symbol_neighbors: []
|
|
878
|
+
},
|
|
879
|
+
'module_b': {
|
|
880
|
+
file: 'b.ts',
|
|
881
|
+
sha: 'sha_b',
|
|
882
|
+
symbol: 'moduleB',
|
|
883
|
+
symbol_calls: ['moduleA'], // Calls back to A
|
|
884
|
+
symbol_neighbors: []
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
888
|
+
// A calls B
|
|
889
|
+
assert.deepEqual(result.module_a.symbol_call_targets, ['sha_b']);
|
|
890
|
+
// B calls A
|
|
891
|
+
assert.deepEqual(result.module_b.symbol_call_targets, ['sha_a']);
|
|
892
|
+
// A is called by B
|
|
893
|
+
assert.deepEqual(result.module_a.symbol_callers, ['sha_b']);
|
|
894
|
+
// B is called by A
|
|
895
|
+
assert.deepEqual(result.module_b.symbol_callers, ['sha_a']);
|
|
896
|
+
// Neighbors should be bidirectional
|
|
897
|
+
assert.deepEqual(result.module_a.symbol_neighbors, ['sha_b']);
|
|
898
|
+
assert.deepEqual(result.module_b.symbol_neighbors, ['sha_a']);
|
|
899
|
+
});
|
|
900
|
+
// ============================================================================
|
|
901
|
+
// Edge Cases and Error Handling
|
|
902
|
+
// ============================================================================
|
|
903
|
+
test('edge case: codemap with invalid entries is handled gracefully', () => {
|
|
904
|
+
const codemap = {
|
|
905
|
+
'valid': {
|
|
906
|
+
file: 'valid.ts',
|
|
907
|
+
sha: 'valid_sha',
|
|
908
|
+
symbol: 'validFunc',
|
|
909
|
+
symbol_calls: [],
|
|
910
|
+
symbol_neighbors: []
|
|
911
|
+
},
|
|
912
|
+
'invalid1': null,
|
|
913
|
+
'invalid2': 'not an object',
|
|
914
|
+
'invalid3': { noSha: true }
|
|
915
|
+
};
|
|
916
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
917
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
918
|
+
// Valid entry should still work
|
|
919
|
+
assert.equal(result.valid.file, 'valid.ts');
|
|
920
|
+
});
|
|
921
|
+
test('edge case: very long symbol names', () => {
|
|
922
|
+
const longSymbol = 'a'.repeat(1000);
|
|
923
|
+
const codemap = {
|
|
924
|
+
'chunk1': {
|
|
925
|
+
file: 'test.ts',
|
|
926
|
+
sha: 'sha1',
|
|
927
|
+
symbol: longSymbol,
|
|
928
|
+
symbol_calls: [longSymbol], // Self-reference should be ignored
|
|
929
|
+
symbol_neighbors: []
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
933
|
+
assert.equal(result.chunk1.symbol, longSymbol);
|
|
934
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, []);
|
|
935
|
+
});
|
|
936
|
+
test('edge case: unicode in symbol names', () => {
|
|
937
|
+
const codemap = {
|
|
938
|
+
'chunk1': {
|
|
939
|
+
file: 'test.ts',
|
|
940
|
+
sha: 'sha1',
|
|
941
|
+
symbol: 'process_data',
|
|
942
|
+
symbol_calls: ['helper_func'],
|
|
943
|
+
symbol_neighbors: []
|
|
944
|
+
},
|
|
945
|
+
'chunk2': {
|
|
946
|
+
file: 'test.ts',
|
|
947
|
+
sha: 'sha2',
|
|
948
|
+
symbol: 'helper_func',
|
|
949
|
+
symbol_calls: [],
|
|
950
|
+
symbol_neighbors: []
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
const result = attachSymbolGraphToCodemap(codemap);
|
|
954
|
+
assert.deepEqual(result.chunk1.symbol_call_targets, ['sha2']);
|
|
955
|
+
});
|
|
956
|
+
test('edge case: special characters in file paths', () => {
|
|
957
|
+
const result = normalizeChunkMetadata({
|
|
958
|
+
file: 'src/components/my-component (copy).tsx',
|
|
959
|
+
sha: 'hash123'
|
|
960
|
+
});
|
|
961
|
+
assert.equal(result.file, 'src/components/my-component (copy).tsx');
|
|
962
|
+
});
|
|
963
|
+
test('edge case: whitespace-only symbol', () => {
|
|
964
|
+
const result = normalizeChunkMetadata({
|
|
965
|
+
file: 'test.ts',
|
|
966
|
+
sha: 'hash',
|
|
967
|
+
symbol: ' '
|
|
968
|
+
});
|
|
969
|
+
assert.equal(result.symbol, null);
|
|
970
|
+
});
|
|
971
|
+
test('edge case: large codemap performance', () => {
|
|
972
|
+
const largeCodemap = {};
|
|
973
|
+
// Create 100 chunks
|
|
974
|
+
for (let i = 0; i < 100; i++) {
|
|
975
|
+
largeCodemap[`chunk_${i}`] = {
|
|
976
|
+
file: `src/file_${i}.ts`,
|
|
977
|
+
sha: `sha_${i}`,
|
|
978
|
+
symbol: `func_${i}`,
|
|
979
|
+
symbol_calls: i > 0 ? [`func_${i - 1}`] : [],
|
|
980
|
+
symbol_neighbors: []
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
const startTime = Date.now();
|
|
984
|
+
const result = attachSymbolGraphToCodemap(largeCodemap);
|
|
985
|
+
const duration = Date.now() - startTime;
|
|
986
|
+
// Should complete in reasonable time (less than 1 second)
|
|
987
|
+
assert.ok(duration < 1000, `Large codemap took ${duration}ms`);
|
|
988
|
+
// Verify chain is built correctly
|
|
989
|
+
assert.deepEqual(result.chunk_1.symbol_call_targets, ['sha_0']);
|
|
990
|
+
assert.deepEqual(result.chunk_99.symbol_call_targets, ['sha_98']);
|
|
991
|
+
});
|
|
992
|
+
//# sourceMappingURL=codemap-io.test.js.map
|