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,826 @@
|
|
|
1
|
+
import test, { describe, beforeEach, afterEach } 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 { getContextPackDirectory, loadContextPack, listContextPacks, getActiveContextPack, setActiveContextPack, resolveScopeWithPack, clearContextPackCache } from '../context/packs.js';
|
|
7
|
+
// Test fixture directory for isolated tests
|
|
8
|
+
let testDir;
|
|
9
|
+
let packDir;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a temporary test directory with optional context packs
|
|
12
|
+
*/
|
|
13
|
+
function setupTestDir() {
|
|
14
|
+
testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'codevault-packs-test-'));
|
|
15
|
+
packDir = path.join(testDir, '.codevault', 'contextpacks');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Cleans up the temporary test directory
|
|
19
|
+
*/
|
|
20
|
+
function cleanupTestDir() {
|
|
21
|
+
if (testDir && fs.existsSync(testDir)) {
|
|
22
|
+
fs.rmSync(testDir, { recursive: true, force: true });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a context pack file with the given content
|
|
27
|
+
*/
|
|
28
|
+
function createPackFile(name, content) {
|
|
29
|
+
if (!fs.existsSync(packDir)) {
|
|
30
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
const filePath = path.join(packDir, `${name}.json`);
|
|
33
|
+
fs.writeFileSync(filePath, JSON.stringify(content, null, 2));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates an invalid JSON file
|
|
37
|
+
*/
|
|
38
|
+
function createInvalidJsonFile(name, content) {
|
|
39
|
+
if (!fs.existsSync(packDir)) {
|
|
40
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
const filePath = path.join(packDir, `${name}.json`);
|
|
43
|
+
fs.writeFileSync(filePath, content);
|
|
44
|
+
}
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// getContextPackDirectory Tests
|
|
47
|
+
// ============================================================================
|
|
48
|
+
describe('getContextPackDirectory', () => {
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
setupTestDir();
|
|
51
|
+
clearContextPackCache();
|
|
52
|
+
});
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
cleanupTestDir();
|
|
55
|
+
});
|
|
56
|
+
test('returns correct directory path with default basePath', () => {
|
|
57
|
+
const result = getContextPackDirectory();
|
|
58
|
+
assert.ok(result.endsWith('.codevault/contextpacks') || result.endsWith('.codevault\\contextpacks'));
|
|
59
|
+
});
|
|
60
|
+
test('returns correct directory path with explicit basePath', () => {
|
|
61
|
+
const result = getContextPackDirectory(testDir);
|
|
62
|
+
const expected = path.join(testDir, '.codevault', 'contextpacks');
|
|
63
|
+
assert.equal(result, expected);
|
|
64
|
+
});
|
|
65
|
+
test('resolves relative path to absolute path', () => {
|
|
66
|
+
const result = getContextPackDirectory('.');
|
|
67
|
+
assert.ok(path.isAbsolute(result));
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// loadContextPack Tests
|
|
72
|
+
// ============================================================================
|
|
73
|
+
describe('loadContextPack', () => {
|
|
74
|
+
beforeEach(() => {
|
|
75
|
+
setupTestDir();
|
|
76
|
+
clearContextPackCache();
|
|
77
|
+
});
|
|
78
|
+
afterEach(() => {
|
|
79
|
+
cleanupTestDir();
|
|
80
|
+
});
|
|
81
|
+
test('throws error for empty pack name', () => {
|
|
82
|
+
assert.throws(() => loadContextPack('', testDir), /Context pack name must be a non-empty string/);
|
|
83
|
+
});
|
|
84
|
+
test('throws error for non-string pack name', () => {
|
|
85
|
+
assert.throws(
|
|
86
|
+
// @ts-expect-error Testing invalid input
|
|
87
|
+
() => loadContextPack(null, testDir), /Context pack name must be a non-empty string/);
|
|
88
|
+
});
|
|
89
|
+
test('throws error for undefined pack name', () => {
|
|
90
|
+
assert.throws(
|
|
91
|
+
// @ts-expect-error Testing invalid input
|
|
92
|
+
() => loadContextPack(undefined, testDir), /Context pack name must be a non-empty string/);
|
|
93
|
+
});
|
|
94
|
+
test('throws error when pack file does not exist', () => {
|
|
95
|
+
assert.throws(() => loadContextPack('nonexistent', testDir), /Context pack "nonexistent" not found/);
|
|
96
|
+
});
|
|
97
|
+
test('loads valid context pack with name and description', () => {
|
|
98
|
+
createPackFile('test-pack', {
|
|
99
|
+
name: 'Test Pack',
|
|
100
|
+
description: 'A test context pack',
|
|
101
|
+
path_glob: ['src/**/*.ts'],
|
|
102
|
+
tags: ['typescript'],
|
|
103
|
+
lang: ['typescript']
|
|
104
|
+
});
|
|
105
|
+
const pack = loadContextPack('test-pack', testDir);
|
|
106
|
+
assert.equal(pack.key, 'test-pack');
|
|
107
|
+
assert.equal(pack.name, 'Test Pack');
|
|
108
|
+
assert.equal(pack.description, 'A test context pack');
|
|
109
|
+
assert.deepEqual(pack.scope.path_glob, ['src/**/*.ts']);
|
|
110
|
+
assert.deepEqual(pack.scope.tags, ['typescript']);
|
|
111
|
+
assert.deepEqual(pack.scope.lang, ['typescript']);
|
|
112
|
+
assert.ok(pack.path.endsWith('test-pack.json'));
|
|
113
|
+
});
|
|
114
|
+
test('loads pack with scope nested in scope property', () => {
|
|
115
|
+
createPackFile('nested-scope', {
|
|
116
|
+
name: 'Nested Scope Pack',
|
|
117
|
+
scope: {
|
|
118
|
+
path_glob: ['lib/**/*.js'],
|
|
119
|
+
lang: ['javascript']
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
const pack = loadContextPack('nested-scope', testDir);
|
|
123
|
+
assert.equal(pack.name, 'Nested Scope Pack');
|
|
124
|
+
assert.deepEqual(pack.scope.path_glob, ['lib/**/*.js']);
|
|
125
|
+
assert.deepEqual(pack.scope.lang, ['javascript']);
|
|
126
|
+
});
|
|
127
|
+
test('uses pack key as name when name is empty', () => {
|
|
128
|
+
createPackFile('unnamed-pack', {
|
|
129
|
+
name: '',
|
|
130
|
+
path_glob: 'src/**'
|
|
131
|
+
});
|
|
132
|
+
const pack = loadContextPack('unnamed-pack', testDir);
|
|
133
|
+
assert.equal(pack.name, 'unnamed-pack');
|
|
134
|
+
});
|
|
135
|
+
test('uses pack key as name when name is whitespace only', () => {
|
|
136
|
+
createPackFile('whitespace-pack', {
|
|
137
|
+
name: ' ',
|
|
138
|
+
path_glob: 'src/**'
|
|
139
|
+
});
|
|
140
|
+
const pack = loadContextPack('whitespace-pack', testDir);
|
|
141
|
+
assert.equal(pack.name, 'whitespace-pack');
|
|
142
|
+
});
|
|
143
|
+
test('uses pack key as name when name is missing', () => {
|
|
144
|
+
createPackFile('no-name-pack', {
|
|
145
|
+
path_glob: 'src/**'
|
|
146
|
+
});
|
|
147
|
+
const pack = loadContextPack('no-name-pack', testDir);
|
|
148
|
+
assert.equal(pack.name, 'no-name-pack');
|
|
149
|
+
});
|
|
150
|
+
test('sets description to null when empty', () => {
|
|
151
|
+
createPackFile('no-desc-pack', {
|
|
152
|
+
name: 'No Description Pack',
|
|
153
|
+
description: ''
|
|
154
|
+
});
|
|
155
|
+
const pack = loadContextPack('no-desc-pack', testDir);
|
|
156
|
+
assert.equal(pack.description, null);
|
|
157
|
+
});
|
|
158
|
+
test('sets description to null when whitespace only', () => {
|
|
159
|
+
createPackFile('whitespace-desc-pack', {
|
|
160
|
+
name: 'Whitespace Description Pack',
|
|
161
|
+
description: ' '
|
|
162
|
+
});
|
|
163
|
+
const pack = loadContextPack('whitespace-desc-pack', testDir);
|
|
164
|
+
assert.equal(pack.description, null);
|
|
165
|
+
});
|
|
166
|
+
test('throws error for invalid JSON in pack file', () => {
|
|
167
|
+
createInvalidJsonFile('invalid-json', '{ invalid json }');
|
|
168
|
+
assert.throws(() => loadContextPack('invalid-json', testDir), /Invalid JSON in context pack/);
|
|
169
|
+
});
|
|
170
|
+
test('throws error for pack with invalid schema', () => {
|
|
171
|
+
createPackFile('invalid-schema', {
|
|
172
|
+
name: 'Invalid Pack',
|
|
173
|
+
unknown_field: 'not allowed'
|
|
174
|
+
});
|
|
175
|
+
assert.throws(() => loadContextPack('invalid-schema', testDir), /unrecognized_keys/ // Zod validation error for strict schema
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
test('caches loaded pack and returns from cache on second call', () => {
|
|
179
|
+
createPackFile('cached-pack', {
|
|
180
|
+
name: 'Cached Pack',
|
|
181
|
+
path_glob: 'src/**'
|
|
182
|
+
});
|
|
183
|
+
const pack1 = loadContextPack('cached-pack', testDir);
|
|
184
|
+
const pack2 = loadContextPack('cached-pack', testDir);
|
|
185
|
+
assert.deepEqual(pack1, pack2);
|
|
186
|
+
});
|
|
187
|
+
test('reloads pack when file mtime changes', async () => {
|
|
188
|
+
createPackFile('mtime-pack', {
|
|
189
|
+
name: 'Original Name',
|
|
190
|
+
path_glob: 'src/**'
|
|
191
|
+
});
|
|
192
|
+
const pack1 = loadContextPack('mtime-pack', testDir);
|
|
193
|
+
assert.equal(pack1.name, 'Original Name');
|
|
194
|
+
// Wait a bit to ensure mtime changes
|
|
195
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
196
|
+
// Update the file
|
|
197
|
+
createPackFile('mtime-pack', {
|
|
198
|
+
name: 'Updated Name',
|
|
199
|
+
path_glob: 'lib/**'
|
|
200
|
+
});
|
|
201
|
+
const pack2 = loadContextPack('mtime-pack', testDir);
|
|
202
|
+
assert.equal(pack2.name, 'Updated Name');
|
|
203
|
+
assert.deepEqual(pack2.scope.path_glob, 'lib/**');
|
|
204
|
+
});
|
|
205
|
+
test('handles pack with boolean scope values', () => {
|
|
206
|
+
createPackFile('boolean-pack', {
|
|
207
|
+
name: 'Boolean Pack',
|
|
208
|
+
hybrid: true,
|
|
209
|
+
bm25: false,
|
|
210
|
+
symbol_boost: true
|
|
211
|
+
});
|
|
212
|
+
const pack = loadContextPack('boolean-pack', testDir);
|
|
213
|
+
assert.equal(pack.scope.hybrid, true);
|
|
214
|
+
assert.equal(pack.scope.bm25, false);
|
|
215
|
+
assert.equal(pack.scope.symbol_boost, true);
|
|
216
|
+
});
|
|
217
|
+
test('handles pack with string boolean values', () => {
|
|
218
|
+
createPackFile('string-bool-pack', {
|
|
219
|
+
name: 'String Boolean Pack',
|
|
220
|
+
hybrid: 'true',
|
|
221
|
+
bm25: 'off',
|
|
222
|
+
symbol_boost: 'on'
|
|
223
|
+
});
|
|
224
|
+
const pack = loadContextPack('string-bool-pack', testDir);
|
|
225
|
+
assert.equal(pack.scope.hybrid, 'true');
|
|
226
|
+
assert.equal(pack.scope.bm25, 'off');
|
|
227
|
+
assert.equal(pack.scope.symbol_boost, 'on');
|
|
228
|
+
});
|
|
229
|
+
test('handles pack with provider and reranker options', () => {
|
|
230
|
+
createPackFile('provider-pack', {
|
|
231
|
+
name: 'Provider Pack',
|
|
232
|
+
provider: 'openai',
|
|
233
|
+
reranker: 'api'
|
|
234
|
+
});
|
|
235
|
+
const pack = loadContextPack('provider-pack', testDir);
|
|
236
|
+
assert.equal(pack.scope.provider, 'openai');
|
|
237
|
+
assert.equal(pack.scope.reranker, 'api');
|
|
238
|
+
});
|
|
239
|
+
test('handles pack with array scope values', () => {
|
|
240
|
+
createPackFile('array-pack', {
|
|
241
|
+
name: 'Array Pack',
|
|
242
|
+
path_glob: ['src/**', 'lib/**'],
|
|
243
|
+
tags: ['core', 'utils'],
|
|
244
|
+
lang: ['typescript', 'javascript']
|
|
245
|
+
});
|
|
246
|
+
const pack = loadContextPack('array-pack', testDir);
|
|
247
|
+
assert.deepEqual(pack.scope.path_glob, ['src/**', 'lib/**']);
|
|
248
|
+
assert.deepEqual(pack.scope.tags, ['core', 'utils']);
|
|
249
|
+
assert.deepEqual(pack.scope.lang, ['typescript', 'javascript']);
|
|
250
|
+
});
|
|
251
|
+
test('handles minimal valid pack (empty object)', () => {
|
|
252
|
+
createPackFile('minimal-pack', {});
|
|
253
|
+
const pack = loadContextPack('minimal-pack', testDir);
|
|
254
|
+
assert.equal(pack.key, 'minimal-pack');
|
|
255
|
+
assert.equal(pack.name, 'minimal-pack');
|
|
256
|
+
assert.equal(pack.description, null);
|
|
257
|
+
assert.deepEqual(pack.scope, {});
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
// ============================================================================
|
|
261
|
+
// listContextPacks Tests
|
|
262
|
+
// ============================================================================
|
|
263
|
+
describe('listContextPacks', () => {
|
|
264
|
+
beforeEach(() => {
|
|
265
|
+
setupTestDir();
|
|
266
|
+
clearContextPackCache();
|
|
267
|
+
});
|
|
268
|
+
afterEach(() => {
|
|
269
|
+
cleanupTestDir();
|
|
270
|
+
});
|
|
271
|
+
test('returns empty array when pack directory does not exist', () => {
|
|
272
|
+
const packs = listContextPacks(testDir);
|
|
273
|
+
assert.deepEqual(packs, []);
|
|
274
|
+
});
|
|
275
|
+
test('returns empty array when pack directory is empty', () => {
|
|
276
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
277
|
+
const packs = listContextPacks(testDir);
|
|
278
|
+
assert.deepEqual(packs, []);
|
|
279
|
+
});
|
|
280
|
+
test('ignores non-json files in pack directory', () => {
|
|
281
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
282
|
+
fs.writeFileSync(path.join(packDir, 'readme.txt'), 'Not a pack');
|
|
283
|
+
fs.writeFileSync(path.join(packDir, 'config.yaml'), 'name: not-pack');
|
|
284
|
+
const packs = listContextPacks(testDir);
|
|
285
|
+
assert.deepEqual(packs, []);
|
|
286
|
+
});
|
|
287
|
+
test('lists all valid context packs', () => {
|
|
288
|
+
createPackFile('pack-a', { name: 'Pack A', path_glob: 'a/**' });
|
|
289
|
+
createPackFile('pack-b', { name: 'Pack B', path_glob: 'b/**' });
|
|
290
|
+
createPackFile('pack-c', { name: 'Pack C', path_glob: 'c/**' });
|
|
291
|
+
const packs = listContextPacks(testDir);
|
|
292
|
+
assert.equal(packs.length, 3);
|
|
293
|
+
const names = packs.map(p => p.name).sort();
|
|
294
|
+
assert.deepEqual(names, ['Pack A', 'Pack B', 'Pack C']);
|
|
295
|
+
});
|
|
296
|
+
test('includes invalid packs with error description', () => {
|
|
297
|
+
createPackFile('valid-pack', { name: 'Valid Pack', path_glob: 'src/**' });
|
|
298
|
+
createInvalidJsonFile('invalid-pack', '{ broken json }');
|
|
299
|
+
const packs = listContextPacks(testDir);
|
|
300
|
+
assert.equal(packs.length, 2);
|
|
301
|
+
const validPack = packs.find(p => p.key === 'valid-pack');
|
|
302
|
+
assert.ok(validPack);
|
|
303
|
+
assert.equal(validPack.invalid, undefined);
|
|
304
|
+
const invalidPack = packs.find(p => p.key === 'invalid-pack');
|
|
305
|
+
assert.ok(invalidPack);
|
|
306
|
+
assert.equal(invalidPack.invalid, true);
|
|
307
|
+
assert.ok(invalidPack.description?.startsWith('Invalid pack:'));
|
|
308
|
+
});
|
|
309
|
+
test('handles schema validation errors gracefully', () => {
|
|
310
|
+
createPackFile('schema-error', {
|
|
311
|
+
name: 'Invalid',
|
|
312
|
+
unknown_property: 'bad value'
|
|
313
|
+
});
|
|
314
|
+
const packs = listContextPacks(testDir);
|
|
315
|
+
assert.equal(packs.length, 1);
|
|
316
|
+
const pack = packs[0];
|
|
317
|
+
assert.equal(pack.key, 'schema-error');
|
|
318
|
+
assert.equal(pack.invalid, true);
|
|
319
|
+
assert.ok(pack.description?.startsWith('Invalid pack:'));
|
|
320
|
+
});
|
|
321
|
+
test('handles active-pack.json file properly (should be filtered out if not a pack)', () => {
|
|
322
|
+
createPackFile('active-pack', {
|
|
323
|
+
key: 'some-pack',
|
|
324
|
+
appliedAt: new Date().toISOString()
|
|
325
|
+
});
|
|
326
|
+
// This should fail schema validation since it has unknown 'key' at root level
|
|
327
|
+
// Actually the schema allows extra properties? Let me check...
|
|
328
|
+
// The schema uses .strict() so this should be filtered as invalid
|
|
329
|
+
const packs = listContextPacks(testDir);
|
|
330
|
+
// Should be marked as invalid due to strict schema
|
|
331
|
+
const activePack = packs.find(p => p.key === 'active-pack');
|
|
332
|
+
if (activePack) {
|
|
333
|
+
assert.equal(activePack.invalid, true);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
// ============================================================================
|
|
338
|
+
// getActiveContextPack Tests
|
|
339
|
+
// ============================================================================
|
|
340
|
+
describe('getActiveContextPack', () => {
|
|
341
|
+
beforeEach(() => {
|
|
342
|
+
setupTestDir();
|
|
343
|
+
clearContextPackCache();
|
|
344
|
+
});
|
|
345
|
+
afterEach(() => {
|
|
346
|
+
cleanupTestDir();
|
|
347
|
+
});
|
|
348
|
+
test('returns null when no active pack state file exists', () => {
|
|
349
|
+
const result = getActiveContextPack(testDir);
|
|
350
|
+
assert.equal(result, null);
|
|
351
|
+
});
|
|
352
|
+
test('returns null when state file contains invalid JSON', () => {
|
|
353
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
354
|
+
fs.writeFileSync(path.join(packDir, 'active-pack.json'), '{ invalid }');
|
|
355
|
+
const result = getActiveContextPack(testDir);
|
|
356
|
+
assert.equal(result, null);
|
|
357
|
+
});
|
|
358
|
+
test('returns null when state file is not an object', () => {
|
|
359
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
360
|
+
fs.writeFileSync(path.join(packDir, 'active-pack.json'), '"just a string"');
|
|
361
|
+
const result = getActiveContextPack(testDir);
|
|
362
|
+
assert.equal(result, null);
|
|
363
|
+
});
|
|
364
|
+
test('returns null when state file has null value', () => {
|
|
365
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
366
|
+
fs.writeFileSync(path.join(packDir, 'active-pack.json'), 'null');
|
|
367
|
+
const result = getActiveContextPack(testDir);
|
|
368
|
+
assert.equal(result, null);
|
|
369
|
+
});
|
|
370
|
+
test('returns null when state file has no key property', () => {
|
|
371
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
372
|
+
fs.writeFileSync(path.join(packDir, 'active-pack.json'), JSON.stringify({ appliedAt: new Date().toISOString() }));
|
|
373
|
+
const result = getActiveContextPack(testDir);
|
|
374
|
+
assert.equal(result, null);
|
|
375
|
+
});
|
|
376
|
+
test('returns null when key is not a string', () => {
|
|
377
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
378
|
+
fs.writeFileSync(path.join(packDir, 'active-pack.json'), JSON.stringify({ key: 123, appliedAt: new Date().toISOString() }));
|
|
379
|
+
const result = getActiveContextPack(testDir);
|
|
380
|
+
assert.equal(result, null);
|
|
381
|
+
});
|
|
382
|
+
test('returns null when referenced pack does not exist', () => {
|
|
383
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
384
|
+
fs.writeFileSync(path.join(packDir, 'active-pack.json'), JSON.stringify({ key: 'nonexistent-pack', appliedAt: new Date().toISOString() }));
|
|
385
|
+
const result = getActiveContextPack(testDir);
|
|
386
|
+
assert.equal(result, null);
|
|
387
|
+
});
|
|
388
|
+
test('returns active pack with appliedAt timestamp', () => {
|
|
389
|
+
const appliedAt = new Date().toISOString();
|
|
390
|
+
createPackFile('my-pack', { name: 'My Pack', path_glob: 'src/**' });
|
|
391
|
+
fs.writeFileSync(path.join(packDir, 'active-pack.json'), JSON.stringify({ key: 'my-pack', appliedAt }));
|
|
392
|
+
const result = getActiveContextPack(testDir);
|
|
393
|
+
assert.ok(result);
|
|
394
|
+
assert.equal(result.key, 'my-pack');
|
|
395
|
+
assert.equal(result.name, 'My Pack');
|
|
396
|
+
assert.equal(result.appliedAt, appliedAt);
|
|
397
|
+
});
|
|
398
|
+
test('returns null appliedAt when not present in state', () => {
|
|
399
|
+
createPackFile('timestamp-pack', { name: 'Timestamp Pack' });
|
|
400
|
+
fs.writeFileSync(path.join(packDir, 'active-pack.json'), JSON.stringify({ key: 'timestamp-pack' }));
|
|
401
|
+
const result = getActiveContextPack(testDir);
|
|
402
|
+
assert.ok(result);
|
|
403
|
+
assert.equal(result.key, 'timestamp-pack');
|
|
404
|
+
assert.equal(result.appliedAt, null);
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
// ============================================================================
|
|
408
|
+
// setActiveContextPack Tests
|
|
409
|
+
// ============================================================================
|
|
410
|
+
describe('setActiveContextPack', () => {
|
|
411
|
+
beforeEach(() => {
|
|
412
|
+
setupTestDir();
|
|
413
|
+
clearContextPackCache();
|
|
414
|
+
});
|
|
415
|
+
afterEach(() => {
|
|
416
|
+
cleanupTestDir();
|
|
417
|
+
});
|
|
418
|
+
test('throws error when pack does not exist', () => {
|
|
419
|
+
assert.throws(() => setActiveContextPack('nonexistent', testDir), /Context pack "nonexistent" not found/);
|
|
420
|
+
});
|
|
421
|
+
test('creates pack directory if it does not exist', () => {
|
|
422
|
+
// Create pack file first, then remove directory to simulate edge case
|
|
423
|
+
createPackFile('auto-dir-pack', { name: 'Auto Dir Pack' });
|
|
424
|
+
// Should succeed and create the active-pack.json
|
|
425
|
+
const result = setActiveContextPack('auto-dir-pack', testDir);
|
|
426
|
+
assert.ok(result);
|
|
427
|
+
assert.ok(fs.existsSync(path.join(packDir, 'active-pack.json')));
|
|
428
|
+
});
|
|
429
|
+
test('sets active pack and returns pack info', () => {
|
|
430
|
+
createPackFile('target-pack', {
|
|
431
|
+
name: 'Target Pack',
|
|
432
|
+
description: 'Pack to activate',
|
|
433
|
+
path_glob: 'src/**'
|
|
434
|
+
});
|
|
435
|
+
const result = setActiveContextPack('target-pack', testDir);
|
|
436
|
+
assert.equal(result.key, 'target-pack');
|
|
437
|
+
assert.equal(result.name, 'Target Pack');
|
|
438
|
+
assert.equal(result.description, 'Pack to activate');
|
|
439
|
+
});
|
|
440
|
+
test('writes state file with key and timestamp', () => {
|
|
441
|
+
createPackFile('state-pack', { name: 'State Pack' });
|
|
442
|
+
const beforeTime = new Date().toISOString();
|
|
443
|
+
setActiveContextPack('state-pack', testDir);
|
|
444
|
+
const afterTime = new Date().toISOString();
|
|
445
|
+
const stateFile = path.join(packDir, 'active-pack.json');
|
|
446
|
+
const stateContent = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
|
|
447
|
+
assert.equal(stateContent.key, 'state-pack');
|
|
448
|
+
assert.ok(stateContent.appliedAt >= beforeTime);
|
|
449
|
+
assert.ok(stateContent.appliedAt <= afterTime);
|
|
450
|
+
});
|
|
451
|
+
test('overwrites previous active pack', () => {
|
|
452
|
+
createPackFile('pack-one', { name: 'Pack One' });
|
|
453
|
+
createPackFile('pack-two', { name: 'Pack Two' });
|
|
454
|
+
setActiveContextPack('pack-one', testDir);
|
|
455
|
+
let active = getActiveContextPack(testDir);
|
|
456
|
+
assert.equal(active?.key, 'pack-one');
|
|
457
|
+
setActiveContextPack('pack-two', testDir);
|
|
458
|
+
active = getActiveContextPack(testDir);
|
|
459
|
+
assert.equal(active?.key, 'pack-two');
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
// ============================================================================
|
|
463
|
+
// resolveScopeWithPack Tests
|
|
464
|
+
// ============================================================================
|
|
465
|
+
describe('resolveScopeWithPack', () => {
|
|
466
|
+
beforeEach(() => {
|
|
467
|
+
setupTestDir();
|
|
468
|
+
clearContextPackCache();
|
|
469
|
+
});
|
|
470
|
+
afterEach(() => {
|
|
471
|
+
cleanupTestDir();
|
|
472
|
+
});
|
|
473
|
+
test('returns default scope when no pack is active and no overrides', () => {
|
|
474
|
+
const result = resolveScopeWithPack({}, { basePath: testDir });
|
|
475
|
+
assert.equal(result.pack, null);
|
|
476
|
+
// Default scope values from normalizeScopeFilters
|
|
477
|
+
assert.equal(result.scope.reranker, 'off');
|
|
478
|
+
assert.equal(result.scope.hybrid, true);
|
|
479
|
+
assert.equal(result.scope.bm25, true);
|
|
480
|
+
assert.equal(result.scope.symbol_boost, true);
|
|
481
|
+
});
|
|
482
|
+
test('applies active pack scope', () => {
|
|
483
|
+
createPackFile('scope-pack', {
|
|
484
|
+
name: 'Scope Pack',
|
|
485
|
+
path_glob: ['src/**'],
|
|
486
|
+
tags: ['api'],
|
|
487
|
+
lang: ['typescript']
|
|
488
|
+
});
|
|
489
|
+
setActiveContextPack('scope-pack', testDir);
|
|
490
|
+
const result = resolveScopeWithPack({}, { basePath: testDir });
|
|
491
|
+
assert.ok(result.pack);
|
|
492
|
+
assert.equal(result.pack.key, 'scope-pack');
|
|
493
|
+
assert.deepEqual(result.scope.path_glob, ['src/**']);
|
|
494
|
+
assert.deepEqual(result.scope.tags, ['api']);
|
|
495
|
+
assert.deepEqual(result.scope.lang, ['typescript']);
|
|
496
|
+
});
|
|
497
|
+
test('overrides can replace pack scope values', () => {
|
|
498
|
+
createPackFile('base-pack', {
|
|
499
|
+
name: 'Base Pack',
|
|
500
|
+
path_glob: ['src/**'],
|
|
501
|
+
lang: ['typescript']
|
|
502
|
+
});
|
|
503
|
+
setActiveContextPack('base-pack', testDir);
|
|
504
|
+
const result = resolveScopeWithPack({ path_glob: ['lib/**'], lang: ['javascript'] }, { basePath: testDir });
|
|
505
|
+
assert.deepEqual(result.scope.path_glob, ['lib/**']);
|
|
506
|
+
assert.deepEqual(result.scope.lang, ['javascript']);
|
|
507
|
+
});
|
|
508
|
+
test('overrides can add to pack scope', () => {
|
|
509
|
+
createPackFile('partial-pack', {
|
|
510
|
+
name: 'Partial Pack',
|
|
511
|
+
path_glob: ['src/**']
|
|
512
|
+
});
|
|
513
|
+
setActiveContextPack('partial-pack', testDir);
|
|
514
|
+
const result = resolveScopeWithPack({ tags: ['important'] }, { basePath: testDir });
|
|
515
|
+
assert.deepEqual(result.scope.path_glob, ['src/**']);
|
|
516
|
+
assert.deepEqual(result.scope.tags, ['important']);
|
|
517
|
+
});
|
|
518
|
+
test('session pack takes precedence over active pack', () => {
|
|
519
|
+
createPackFile('active-pack', {
|
|
520
|
+
name: 'Active Pack',
|
|
521
|
+
path_glob: ['active/**']
|
|
522
|
+
});
|
|
523
|
+
setActiveContextPack('active-pack', testDir);
|
|
524
|
+
const sessionPack = {
|
|
525
|
+
key: 'session-pack',
|
|
526
|
+
name: 'Session Pack',
|
|
527
|
+
description: 'Temporary session scope',
|
|
528
|
+
scope: { path_glob: ['session/**'] },
|
|
529
|
+
path: '/tmp/session-pack.json',
|
|
530
|
+
basePath: testDir
|
|
531
|
+
};
|
|
532
|
+
const result = resolveScopeWithPack({}, { basePath: testDir, sessionPack });
|
|
533
|
+
assert.ok(result.pack);
|
|
534
|
+
assert.equal(result.pack.key, 'session-pack');
|
|
535
|
+
assert.deepEqual(result.scope.path_glob, ['session/**']);
|
|
536
|
+
});
|
|
537
|
+
test('session pack is ignored when basePath differs', () => {
|
|
538
|
+
// Create the pack file
|
|
539
|
+
createPackFile('active-pack', {
|
|
540
|
+
name: 'Active Pack',
|
|
541
|
+
path_glob: ['active/**']
|
|
542
|
+
});
|
|
543
|
+
// Verify pack file exists
|
|
544
|
+
const packFile = path.join(packDir, 'active-pack.json');
|
|
545
|
+
assert.ok(fs.existsSync(packFile), `Pack file should exist at ${packFile}`);
|
|
546
|
+
// Load the pack directly to verify it works
|
|
547
|
+
const loadedPack = loadContextPack('active-pack', testDir);
|
|
548
|
+
assert.equal(loadedPack.name, 'Active Pack', 'Pack should load correctly');
|
|
549
|
+
// Set it as active
|
|
550
|
+
setActiveContextPack('active-pack', testDir);
|
|
551
|
+
// Verify the state file was created
|
|
552
|
+
const stateFile = path.join(packDir, 'active-pack.json');
|
|
553
|
+
assert.ok(fs.existsSync(stateFile), 'State file should exist');
|
|
554
|
+
// Verify the active pack can be retrieved
|
|
555
|
+
const activePack = getActiveContextPack(testDir);
|
|
556
|
+
assert.ok(activePack, 'Active pack should be retrievable');
|
|
557
|
+
assert.equal(activePack.key, 'active-pack');
|
|
558
|
+
const sessionPack = {
|
|
559
|
+
key: 'session-pack',
|
|
560
|
+
name: 'Session Pack',
|
|
561
|
+
description: null,
|
|
562
|
+
scope: { path_glob: ['session/**'] },
|
|
563
|
+
path: '/other/session-pack.json',
|
|
564
|
+
basePath: '/different/path'
|
|
565
|
+
};
|
|
566
|
+
const result = resolveScopeWithPack({}, { basePath: testDir, sessionPack });
|
|
567
|
+
// Session pack is ignored because its basePath differs from testDir
|
|
568
|
+
// So the active pack should be used instead
|
|
569
|
+
assert.ok(result.pack, 'Active pack should be found when session pack basePath differs');
|
|
570
|
+
assert.equal(result.pack.key, 'active-pack');
|
|
571
|
+
assert.deepEqual(result.scope.path_glob, ['active/**']);
|
|
572
|
+
});
|
|
573
|
+
test('overrides take precedence over session pack', () => {
|
|
574
|
+
const sessionPack = {
|
|
575
|
+
key: 'session-pack',
|
|
576
|
+
name: 'Session Pack',
|
|
577
|
+
description: null,
|
|
578
|
+
scope: { path_glob: ['session/**'], lang: ['python'] },
|
|
579
|
+
path: '/tmp/session-pack.json',
|
|
580
|
+
basePath: testDir
|
|
581
|
+
};
|
|
582
|
+
const result = resolveScopeWithPack({ lang: ['ruby'] }, { basePath: testDir, sessionPack });
|
|
583
|
+
assert.deepEqual(result.scope.path_glob, ['session/**']);
|
|
584
|
+
assert.deepEqual(result.scope.lang, ['ruby']);
|
|
585
|
+
});
|
|
586
|
+
test('handles undefined overrides', () => {
|
|
587
|
+
createPackFile('undef-test', {
|
|
588
|
+
name: 'Undef Test',
|
|
589
|
+
path_glob: ['src/**']
|
|
590
|
+
});
|
|
591
|
+
setActiveContextPack('undef-test', testDir);
|
|
592
|
+
const result = resolveScopeWithPack({ path_glob: undefined, tags: undefined }, { basePath: testDir });
|
|
593
|
+
assert.deepEqual(result.scope.path_glob, ['src/**']);
|
|
594
|
+
assert.equal(result.scope.tags, undefined);
|
|
595
|
+
});
|
|
596
|
+
test('normalizes scope values', () => {
|
|
597
|
+
createPackFile('normalize-pack', {
|
|
598
|
+
name: 'Normalize Pack',
|
|
599
|
+
tags: 'single-tag',
|
|
600
|
+
lang: 'TypeScript',
|
|
601
|
+
hybrid: 'on',
|
|
602
|
+
bm25: 'off'
|
|
603
|
+
});
|
|
604
|
+
setActiveContextPack('normalize-pack', testDir);
|
|
605
|
+
const result = resolveScopeWithPack({}, { basePath: testDir });
|
|
606
|
+
// Tags and lang should be normalized to lowercase arrays
|
|
607
|
+
assert.deepEqual(result.scope.tags, ['single-tag']);
|
|
608
|
+
assert.deepEqual(result.scope.lang, ['typescript']);
|
|
609
|
+
assert.equal(result.scope.hybrid, true);
|
|
610
|
+
assert.equal(result.scope.bm25, false);
|
|
611
|
+
});
|
|
612
|
+
test('returns pack info with description', () => {
|
|
613
|
+
createPackFile('info-pack', {
|
|
614
|
+
name: 'Info Pack',
|
|
615
|
+
description: 'Pack with description'
|
|
616
|
+
});
|
|
617
|
+
setActiveContextPack('info-pack', testDir);
|
|
618
|
+
const result = resolveScopeWithPack({}, { basePath: testDir });
|
|
619
|
+
assert.ok(result.pack);
|
|
620
|
+
assert.equal(result.pack.key, 'info-pack');
|
|
621
|
+
assert.equal(result.pack.name, 'Info Pack');
|
|
622
|
+
assert.equal(result.pack.description, 'Pack with description');
|
|
623
|
+
});
|
|
624
|
+
test('works with default options', () => {
|
|
625
|
+
// Uses current working directory
|
|
626
|
+
const result = resolveScopeWithPack();
|
|
627
|
+
// Should not throw and return default scope
|
|
628
|
+
assert.ok(result);
|
|
629
|
+
assert.equal(result.scope.hybrid, true);
|
|
630
|
+
});
|
|
631
|
+
test('handles empty session pack scope', () => {
|
|
632
|
+
const sessionPack = {
|
|
633
|
+
key: 'empty-session',
|
|
634
|
+
name: 'Empty Session',
|
|
635
|
+
description: null,
|
|
636
|
+
scope: {},
|
|
637
|
+
path: '/tmp/empty.json',
|
|
638
|
+
basePath: testDir
|
|
639
|
+
};
|
|
640
|
+
const result = resolveScopeWithPack({ path_glob: ['override/**'] }, { basePath: testDir, sessionPack });
|
|
641
|
+
assert.ok(result.pack);
|
|
642
|
+
assert.equal(result.pack.key, 'empty-session');
|
|
643
|
+
assert.deepEqual(result.scope.path_glob, ['override/**']);
|
|
644
|
+
});
|
|
645
|
+
test('handles session pack with null scope', () => {
|
|
646
|
+
const sessionPack = {
|
|
647
|
+
key: 'null-scope-session',
|
|
648
|
+
name: 'Null Scope Session',
|
|
649
|
+
description: null,
|
|
650
|
+
scope: {},
|
|
651
|
+
path: '/tmp/null-scope.json',
|
|
652
|
+
basePath: testDir
|
|
653
|
+
};
|
|
654
|
+
const result = resolveScopeWithPack({}, { basePath: testDir, sessionPack });
|
|
655
|
+
assert.ok(result.pack);
|
|
656
|
+
assert.equal(result.pack.key, 'null-scope-session');
|
|
657
|
+
});
|
|
658
|
+
test('handles provider override', () => {
|
|
659
|
+
createPackFile('provider-base', {
|
|
660
|
+
name: 'Provider Base',
|
|
661
|
+
provider: 'openai'
|
|
662
|
+
});
|
|
663
|
+
setActiveContextPack('provider-base', testDir);
|
|
664
|
+
const result = resolveScopeWithPack({ provider: 'anthropic' }, { basePath: testDir });
|
|
665
|
+
assert.equal(result.scope.provider, 'anthropic');
|
|
666
|
+
});
|
|
667
|
+
test('handles reranker override', () => {
|
|
668
|
+
createPackFile('reranker-base', {
|
|
669
|
+
name: 'Reranker Base',
|
|
670
|
+
reranker: 'off'
|
|
671
|
+
});
|
|
672
|
+
setActiveContextPack('reranker-base', testDir);
|
|
673
|
+
const result = resolveScopeWithPack({ reranker: 'api' }, { basePath: testDir });
|
|
674
|
+
assert.equal(result.scope.reranker, 'api');
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
// ============================================================================
|
|
678
|
+
// clearContextPackCache Tests
|
|
679
|
+
// ============================================================================
|
|
680
|
+
describe('clearContextPackCache', () => {
|
|
681
|
+
beforeEach(() => {
|
|
682
|
+
setupTestDir();
|
|
683
|
+
clearContextPackCache();
|
|
684
|
+
});
|
|
685
|
+
afterEach(() => {
|
|
686
|
+
cleanupTestDir();
|
|
687
|
+
});
|
|
688
|
+
test('clears cached packs', () => {
|
|
689
|
+
createPackFile('cache-test', {
|
|
690
|
+
name: 'Cache Test',
|
|
691
|
+
path_glob: 'original/**'
|
|
692
|
+
});
|
|
693
|
+
// Load to cache
|
|
694
|
+
const pack1 = loadContextPack('cache-test', testDir);
|
|
695
|
+
assert.equal(pack1.name, 'Cache Test');
|
|
696
|
+
// Modify file without changing mtime (simulating edge case)
|
|
697
|
+
// Actually we need to clear cache to force reload
|
|
698
|
+
clearContextPackCache();
|
|
699
|
+
// Update file content
|
|
700
|
+
createPackFile('cache-test', {
|
|
701
|
+
name: 'Updated Cache Test',
|
|
702
|
+
path_glob: 'updated/**'
|
|
703
|
+
});
|
|
704
|
+
// Should get updated version
|
|
705
|
+
const pack2 = loadContextPack('cache-test', testDir);
|
|
706
|
+
assert.equal(pack2.name, 'Updated Cache Test');
|
|
707
|
+
});
|
|
708
|
+
test('does not throw on empty cache', () => {
|
|
709
|
+
// Should not throw
|
|
710
|
+
clearContextPackCache();
|
|
711
|
+
clearContextPackCache();
|
|
712
|
+
assert.ok(true);
|
|
713
|
+
});
|
|
714
|
+
});
|
|
715
|
+
// ============================================================================
|
|
716
|
+
// Edge Cases and Error Handling
|
|
717
|
+
// ============================================================================
|
|
718
|
+
describe('Edge Cases', () => {
|
|
719
|
+
beforeEach(() => {
|
|
720
|
+
setupTestDir();
|
|
721
|
+
clearContextPackCache();
|
|
722
|
+
});
|
|
723
|
+
afterEach(() => {
|
|
724
|
+
cleanupTestDir();
|
|
725
|
+
});
|
|
726
|
+
test('handles pack with all scope keys', () => {
|
|
727
|
+
createPackFile('full-pack', {
|
|
728
|
+
name: 'Full Pack',
|
|
729
|
+
description: 'Pack with all scope keys',
|
|
730
|
+
path_glob: ['**/*.ts'],
|
|
731
|
+
tags: ['core'],
|
|
732
|
+
lang: ['typescript'],
|
|
733
|
+
provider: 'openai',
|
|
734
|
+
reranker: 'api',
|
|
735
|
+
hybrid: true,
|
|
736
|
+
bm25: true,
|
|
737
|
+
symbol_boost: false
|
|
738
|
+
});
|
|
739
|
+
const pack = loadContextPack('full-pack', testDir);
|
|
740
|
+
// Arrays are stored as-is in the pack scope
|
|
741
|
+
assert.deepEqual(pack.scope.path_glob, ['**/*.ts']);
|
|
742
|
+
assert.deepEqual(pack.scope.tags, ['core']);
|
|
743
|
+
assert.deepEqual(pack.scope.lang, ['typescript']);
|
|
744
|
+
assert.equal(pack.scope.provider, 'openai');
|
|
745
|
+
assert.equal(pack.scope.reranker, 'api');
|
|
746
|
+
assert.equal(pack.scope.hybrid, true);
|
|
747
|
+
assert.equal(pack.scope.bm25, true);
|
|
748
|
+
assert.equal(pack.scope.symbol_boost, false);
|
|
749
|
+
});
|
|
750
|
+
test('handles special characters in pack name', () => {
|
|
751
|
+
createPackFile('pack-with-dashes', { name: 'Dashed Pack' });
|
|
752
|
+
createPackFile('pack_with_underscores', { name: 'Underscored Pack' });
|
|
753
|
+
const dashed = loadContextPack('pack-with-dashes', testDir);
|
|
754
|
+
const underscored = loadContextPack('pack_with_underscores', testDir);
|
|
755
|
+
assert.equal(dashed.name, 'Dashed Pack');
|
|
756
|
+
assert.equal(underscored.name, 'Underscored Pack');
|
|
757
|
+
});
|
|
758
|
+
test('handles deeply nested scope in pack definition', () => {
|
|
759
|
+
createPackFile('nested-deep', {
|
|
760
|
+
name: 'Nested Deep',
|
|
761
|
+
scope: {
|
|
762
|
+
path_glob: 'scope-path/**',
|
|
763
|
+
tags: ['scope-tag']
|
|
764
|
+
},
|
|
765
|
+
// Top-level values should merge with scope
|
|
766
|
+
lang: ['toplevel-lang']
|
|
767
|
+
});
|
|
768
|
+
const pack = loadContextPack('nested-deep', testDir);
|
|
769
|
+
// Both scope-level and top-level values should be captured
|
|
770
|
+
// Values are stored as-is (string stays string, array stays array)
|
|
771
|
+
assert.equal(pack.scope.path_glob, 'scope-path/**');
|
|
772
|
+
assert.deepEqual(pack.scope.tags, ['scope-tag']);
|
|
773
|
+
assert.deepEqual(pack.scope.lang, ['toplevel-lang']);
|
|
774
|
+
});
|
|
775
|
+
test('handles pack with metadata field', () => {
|
|
776
|
+
createPackFile('metadata-pack', {
|
|
777
|
+
name: 'Metadata Pack',
|
|
778
|
+
description: 'Has metadata',
|
|
779
|
+
metadata: {
|
|
780
|
+
author: 'test',
|
|
781
|
+
version: '1.0.0'
|
|
782
|
+
},
|
|
783
|
+
path_glob: 'src/**'
|
|
784
|
+
});
|
|
785
|
+
const pack = loadContextPack('metadata-pack', testDir);
|
|
786
|
+
assert.equal(pack.name, 'Metadata Pack');
|
|
787
|
+
// Metadata is allowed but not included in scope
|
|
788
|
+
assert.equal(pack.scope.path_glob, 'src/**');
|
|
789
|
+
});
|
|
790
|
+
test('resolveScopeWithPack handles missing basePath in options', () => {
|
|
791
|
+
const result = resolveScopeWithPack({}, {});
|
|
792
|
+
// Should use default basePath '.'
|
|
793
|
+
assert.ok(result);
|
|
794
|
+
assert.equal(result.scope.hybrid, true);
|
|
795
|
+
});
|
|
796
|
+
test('pack path is absolute', () => {
|
|
797
|
+
createPackFile('abs-path-pack', { name: 'Abs Path Pack' });
|
|
798
|
+
const pack = loadContextPack('abs-path-pack', testDir);
|
|
799
|
+
assert.ok(path.isAbsolute(pack.path));
|
|
800
|
+
assert.ok(pack.path.includes('abs-path-pack.json'));
|
|
801
|
+
});
|
|
802
|
+
test('concurrent loads return same cached value', async () => {
|
|
803
|
+
createPackFile('concurrent-pack', { name: 'Concurrent Pack' });
|
|
804
|
+
// Load same pack concurrently
|
|
805
|
+
const [pack1, pack2, pack3] = await Promise.all([
|
|
806
|
+
Promise.resolve(loadContextPack('concurrent-pack', testDir)),
|
|
807
|
+
Promise.resolve(loadContextPack('concurrent-pack', testDir)),
|
|
808
|
+
Promise.resolve(loadContextPack('concurrent-pack', testDir))
|
|
809
|
+
]);
|
|
810
|
+
assert.deepEqual(pack1, pack2);
|
|
811
|
+
assert.deepEqual(pack2, pack3);
|
|
812
|
+
});
|
|
813
|
+
test('listContextPacks with mixed valid and invalid packs', () => {
|
|
814
|
+
createPackFile('valid-1', { name: 'Valid 1' });
|
|
815
|
+
createInvalidJsonFile('invalid-1', 'not json');
|
|
816
|
+
createPackFile('valid-2', { name: 'Valid 2' });
|
|
817
|
+
createPackFile('schema-invalid', { name: 'Schema Invalid', bad_key: true });
|
|
818
|
+
createInvalidJsonFile('invalid-2', '{ "unclosed": }');
|
|
819
|
+
const packs = listContextPacks(testDir);
|
|
820
|
+
const valid = packs.filter(p => !p.invalid);
|
|
821
|
+
const invalid = packs.filter(p => p.invalid);
|
|
822
|
+
assert.equal(valid.length, 2);
|
|
823
|
+
assert.equal(invalid.length, 3);
|
|
824
|
+
});
|
|
825
|
+
});
|
|
826
|
+
//# sourceMappingURL=context-packs.test.js.map
|