lmgrep 0.1.18 → 0.2.1
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 +253 -62
- package/completions/_lmgrep +49 -40
- package/dist/application/Lmgrep.d.ts +107 -0
- package/dist/application/Lmgrep.js +99 -0
- package/dist/application/Lmgrep.js.map +1 -0
- package/dist/application/LmgrepFactory.d.ts +40 -0
- package/dist/application/LmgrepFactory.js +155 -0
- package/dist/application/LmgrepFactory.js.map +1 -0
- package/dist/application/indexing/BranchBootstrapper.d.ts +21 -0
- package/dist/application/indexing/BranchBootstrapper.js +52 -0
- package/dist/application/indexing/BranchBootstrapper.js.map +1 -0
- package/dist/application/indexing/BranchManifestSweeper.d.ts +17 -0
- package/dist/application/indexing/BranchManifestSweeper.js +35 -0
- package/dist/application/indexing/BranchManifestSweeper.js.map +1 -0
- package/dist/application/indexing/Duration.d.ts +9 -0
- package/dist/application/indexing/Duration.js +25 -0
- package/dist/application/indexing/Duration.js.map +1 -0
- package/dist/application/indexing/EmbeddingAbortError.d.ts +11 -0
- package/dist/application/indexing/EmbeddingAbortError.js +20 -0
- package/dist/application/indexing/EmbeddingAbortError.js.map +1 -0
- package/dist/application/indexing/EmbeddingPipeline.d.ts +59 -0
- package/dist/application/indexing/EmbeddingPipeline.js +140 -0
- package/dist/application/indexing/EmbeddingPipeline.js.map +1 -0
- package/dist/application/indexing/IndexBuilder.d.ts +112 -0
- package/dist/application/indexing/IndexBuilder.js +370 -0
- package/dist/application/indexing/IndexBuilder.js.map +1 -0
- package/dist/application/indexing/IndexingProgress.d.ts +34 -0
- package/dist/application/indexing/IndexingProgress.js +2 -0
- package/dist/application/indexing/IndexingProgress.js.map +1 -0
- package/dist/application/operations/Deadline.d.ts +13 -0
- package/dist/application/operations/Deadline.js +29 -0
- package/dist/application/operations/Deadline.js.map +1 -0
- package/dist/application/operations/HealthMonitor.d.ts +58 -0
- package/dist/application/operations/HealthMonitor.js +128 -0
- package/dist/application/operations/HealthMonitor.js.map +1 -0
- package/dist/application/operations/IndexAlternatives.d.ts +35 -0
- package/dist/application/operations/IndexAlternatives.js +61 -0
- package/dist/application/operations/IndexAlternatives.js.map +1 -0
- package/dist/application/operations/IndexInventory.d.ts +69 -0
- package/dist/application/operations/IndexInventory.js +99 -0
- package/dist/application/operations/IndexInventory.js.map +1 -0
- package/dist/application/operations/StatusService.d.ts +90 -0
- package/dist/application/operations/StatusService.js +171 -0
- package/dist/application/operations/StatusService.js.map +1 -0
- package/dist/application/operations/WatchService.d.ts +67 -0
- package/dist/application/operations/WatchService.js +145 -0
- package/dist/application/operations/WatchService.js.map +1 -0
- package/dist/application/operations/WorkingTreeDiff.d.ts +19 -0
- package/dist/application/operations/WorkingTreeDiff.js +36 -0
- package/dist/application/operations/WorkingTreeDiff.js.map +1 -0
- package/dist/application/research/ResearchAgent.d.ts +68 -0
- package/dist/application/research/ResearchAgent.js +201 -0
- package/dist/application/research/ResearchAgent.js.map +1 -0
- package/dist/application/research/ResearchPrompts.d.ts +16 -0
- package/dist/application/research/ResearchPrompts.js +34 -0
- package/dist/application/research/ResearchPrompts.js.map +1 -0
- package/dist/application/search/SearchCriteria.d.ts +37 -0
- package/dist/application/search/SearchCriteria.js +48 -0
- package/dist/application/search/SearchCriteria.js.map +1 -0
- package/dist/application/search/SearchService.d.ts +36 -0
- package/dist/application/search/SearchService.js +108 -0
- package/dist/application/search/SearchService.js.map +1 -0
- package/dist/application/search/SearchTargetResolver.d.ts +56 -0
- package/dist/application/search/SearchTargetResolver.js +104 -0
- package/dist/application/search/SearchTargetResolver.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +4 -953
- package/dist/cli.js.map +1 -1
- package/dist/domain/config/ConfigSource.d.ts +16 -0
- package/dist/domain/config/ConfigSource.js +2 -0
- package/dist/domain/config/ConfigSource.js.map +1 -0
- package/dist/domain/config/LmgrepConfig.d.ts +53 -0
- package/dist/domain/config/LmgrepConfig.js +2 -0
- package/dist/domain/config/LmgrepConfig.js.map +1 -0
- package/dist/domain/corpus/Chunk.d.ts +49 -0
- package/dist/domain/corpus/Chunk.js +60 -0
- package/dist/domain/corpus/Chunk.js.map +1 -0
- package/dist/domain/corpus/CodeLocation.d.ts +18 -0
- package/dist/domain/corpus/CodeLocation.js +34 -0
- package/dist/domain/corpus/CodeLocation.js.map +1 -0
- package/dist/domain/corpus/ContentHash.d.ts +15 -0
- package/dist/domain/corpus/ContentHash.js +30 -0
- package/dist/domain/corpus/ContentHash.js.map +1 -0
- package/dist/domain/corpus/FileVersion.d.ts +31 -0
- package/dist/domain/corpus/FileVersion.js +47 -0
- package/dist/domain/corpus/FileVersion.js.map +1 -0
- package/dist/domain/corpus/SourceFile.d.ts +26 -0
- package/dist/domain/corpus/SourceFile.js +47 -0
- package/dist/domain/corpus/SourceFile.js.map +1 -0
- package/dist/domain/corpus/Vector.d.ts +37 -0
- package/dist/domain/corpus/Vector.js +96 -0
- package/dist/domain/corpus/Vector.js.map +1 -0
- package/dist/domain/ports/ChatModelPort.d.ts +57 -0
- package/dist/domain/ports/ChatModelPort.js +2 -0
- package/dist/domain/ports/ChatModelPort.js.map +1 -0
- package/dist/domain/ports/ChunkRepositoryPort.d.ts +42 -0
- package/dist/domain/ports/ChunkRepositoryPort.js +2 -0
- package/dist/domain/ports/ChunkRepositoryPort.js.map +1 -0
- package/dist/domain/ports/ChunkerPort.d.ts +5 -0
- package/dist/domain/ports/ChunkerPort.js +2 -0
- package/dist/domain/ports/ChunkerPort.js.map +1 -0
- package/dist/domain/ports/DatabaseSessionPort.d.ts +10 -0
- package/dist/domain/ports/DatabaseSessionPort.js +2 -0
- package/dist/domain/ports/DatabaseSessionPort.js.map +1 -0
- package/dist/domain/ports/EmbedderPort.d.ts +14 -0
- package/dist/domain/ports/EmbedderPort.js +2 -0
- package/dist/domain/ports/EmbedderPort.js.map +1 -0
- package/dist/domain/ports/FileManifestRepositoryPort.d.ts +32 -0
- package/dist/domain/ports/FileManifestRepositoryPort.js +2 -0
- package/dist/domain/ports/FileManifestRepositoryPort.js.map +1 -0
- package/dist/domain/ports/GitPort.d.ts +24 -0
- package/dist/domain/ports/GitPort.js +2 -0
- package/dist/domain/ports/GitPort.js.map +1 -0
- package/dist/domain/ports/IndexMaintenancePort.d.ts +58 -0
- package/dist/domain/ports/IndexMaintenancePort.js +2 -0
- package/dist/domain/ports/IndexMaintenancePort.js.map +1 -0
- package/dist/domain/ports/IndexMetadataPort.d.ts +23 -0
- package/dist/domain/ports/IndexMetadataPort.js +2 -0
- package/dist/domain/ports/IndexMetadataPort.js.map +1 -0
- package/dist/domain/ports/LockPort.d.ts +17 -0
- package/dist/domain/ports/LockPort.js +2 -0
- package/dist/domain/ports/LockPort.js.map +1 -0
- package/dist/domain/ports/LoggerPort.d.ts +5 -0
- package/dist/domain/ports/LoggerPort.js +2 -0
- package/dist/domain/ports/LoggerPort.js.map +1 -0
- package/dist/domain/ports/ProjectIndexesPort.d.ts +20 -0
- package/dist/domain/ports/ProjectIndexesPort.js +2 -0
- package/dist/domain/ports/ProjectIndexesPort.js.map +1 -0
- package/dist/domain/ports/ProjectRegistryPort.d.ts +42 -0
- package/dist/domain/ports/ProjectRegistryPort.js +2 -0
- package/dist/domain/ports/ProjectRegistryPort.js.map +1 -0
- package/dist/domain/ports/StateDirectoryPort.d.ts +29 -0
- package/dist/domain/ports/StateDirectoryPort.js +2 -0
- package/dist/domain/ports/StateDirectoryPort.js.map +1 -0
- package/dist/domain/ports/WorkspacePort.d.ts +38 -0
- package/dist/domain/ports/WorkspacePort.js +2 -0
- package/dist/domain/ports/WorkspacePort.js.map +1 -0
- package/dist/domain/project/Branch.d.ts +20 -0
- package/dist/domain/project/Branch.js +33 -0
- package/dist/domain/project/Branch.js.map +1 -0
- package/dist/domain/project/DatabaseLocation.d.ts +32 -0
- package/dist/domain/project/DatabaseLocation.js +35 -0
- package/dist/domain/project/DatabaseLocation.js.map +1 -0
- package/dist/domain/project/IndexMetadata.d.ts +17 -0
- package/dist/domain/project/IndexMetadata.js +2 -0
- package/dist/domain/project/IndexMetadata.js.map +1 -0
- package/dist/domain/project/ModelIdentity.d.ts +58 -0
- package/dist/domain/project/ModelIdentity.js +94 -0
- package/dist/domain/project/ModelIdentity.js.map +1 -0
- package/dist/domain/project/Project.d.ts +17 -0
- package/dist/domain/project/Project.js +21 -0
- package/dist/domain/project/Project.js.map +1 -0
- package/dist/domain/project/ProjectId.d.ts +28 -0
- package/dist/domain/project/ProjectId.js +58 -0
- package/dist/domain/project/ProjectId.js.map +1 -0
- package/dist/domain/project/ProjectLocator.d.ts +112 -0
- package/dist/domain/project/ProjectLocator.js +178 -0
- package/dist/domain/project/ProjectLocator.js.map +1 -0
- package/dist/domain/research/Citation.d.ts +27 -0
- package/dist/domain/research/Citation.js +43 -0
- package/dist/domain/research/Citation.js.map +1 -0
- package/dist/domain/research/EvidenceLedger.d.ts +47 -0
- package/dist/domain/research/EvidenceLedger.js +111 -0
- package/dist/domain/research/EvidenceLedger.js.map +1 -0
- package/dist/domain/research/ResearchTrace.d.ts +19 -0
- package/dist/domain/research/ResearchTrace.js +22 -0
- package/dist/domain/research/ResearchTrace.js.map +1 -0
- package/dist/domain/retrieval/Hit.d.ts +19 -0
- package/dist/domain/retrieval/Hit.js +28 -0
- package/dist/domain/retrieval/Hit.js.map +1 -0
- package/dist/domain/retrieval/HitList.d.ts +35 -0
- package/dist/domain/retrieval/HitList.js +81 -0
- package/dist/domain/retrieval/HitList.js.map +1 -0
- package/dist/domain/retrieval/MissingIndexError.d.ts +11 -0
- package/dist/domain/retrieval/MissingIndexError.js +15 -0
- package/dist/domain/retrieval/MissingIndexError.js.map +1 -0
- package/dist/index.d.ts +43 -45
- package/dist/index.js +30 -567
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/ai/AiSdkChatModel.d.ts +31 -0
- package/dist/infrastructure/ai/AiSdkChatModel.js +137 -0
- package/dist/infrastructure/ai/AiSdkChatModel.js.map +1 -0
- package/dist/infrastructure/ai/AiSdkEmbedder.d.ts +28 -0
- package/dist/infrastructure/ai/AiSdkEmbedder.js +79 -0
- package/dist/infrastructure/ai/AiSdkEmbedder.js.map +1 -0
- package/dist/infrastructure/ai/DockerModelRunnerProbe.d.ts +16 -0
- package/dist/infrastructure/ai/DockerModelRunnerProbe.js +52 -0
- package/dist/infrastructure/ai/DockerModelRunnerProbe.js.map +1 -0
- package/dist/infrastructure/ai/EmbeddingPrefixes.d.ts +21 -0
- package/dist/infrastructure/ai/EmbeddingPrefixes.js +40 -0
- package/dist/infrastructure/ai/EmbeddingPrefixes.js.map +1 -0
- package/dist/infrastructure/ai/LmStudioProbe.d.ts +18 -0
- package/dist/infrastructure/ai/LmStudioProbe.js +49 -0
- package/dist/infrastructure/ai/LmStudioProbe.js.map +1 -0
- package/dist/infrastructure/ai/LocalModelReloader.d.ts +21 -0
- package/dist/infrastructure/ai/LocalModelReloader.js +61 -0
- package/dist/infrastructure/ai/LocalModelReloader.js.map +1 -0
- package/dist/infrastructure/ai/LocalRuntimeDetector.d.ts +36 -0
- package/dist/infrastructure/ai/LocalRuntimeDetector.js +63 -0
- package/dist/infrastructure/ai/LocalRuntimeDetector.js.map +1 -0
- package/dist/infrastructure/ai/ModelRuntime.d.ts +32 -0
- package/dist/infrastructure/ai/ModelRuntime.js +2 -0
- package/dist/infrastructure/ai/ModelRuntime.js.map +1 -0
- package/dist/infrastructure/ai/OllamaProbe.d.ts +22 -0
- package/dist/infrastructure/ai/OllamaProbe.js +71 -0
- package/dist/infrastructure/ai/OllamaProbe.js.map +1 -0
- package/dist/infrastructure/ai/ProviderFailure.d.ts +16 -0
- package/dist/infrastructure/ai/ProviderFailure.js +35 -0
- package/dist/infrastructure/ai/ProviderFailure.js.map +1 -0
- package/dist/infrastructure/ai/ProviderModuleLoader.d.ts +14 -0
- package/dist/infrastructure/ai/ProviderModuleLoader.js +56 -0
- package/dist/infrastructure/ai/ProviderModuleLoader.js.map +1 -0
- package/dist/infrastructure/ai/ProviderRegistry.d.ts +38 -0
- package/dist/infrastructure/ai/ProviderRegistry.js +63 -0
- package/dist/infrastructure/ai/ProviderRegistry.js.map +1 -0
- package/dist/infrastructure/fs/ConfigLoader.d.ts +59 -0
- package/dist/infrastructure/fs/ConfigLoader.js +194 -0
- package/dist/infrastructure/fs/ConfigLoader.js.map +1 -0
- package/dist/infrastructure/fs/DatabaseLocks.d.ts +52 -0
- package/dist/infrastructure/fs/DatabaseLocks.js +92 -0
- package/dist/infrastructure/fs/DatabaseLocks.js.map +1 -0
- package/dist/infrastructure/fs/DiskUsage.d.ts +6 -0
- package/dist/infrastructure/fs/DiskUsage.js +41 -0
- package/dist/infrastructure/fs/DiskUsage.js.map +1 -0
- package/dist/infrastructure/fs/IndexableFileRules.d.ts +33 -0
- package/dist/infrastructure/fs/IndexableFileRules.js +177 -0
- package/dist/infrastructure/fs/IndexableFileRules.js.map +1 -0
- package/dist/infrastructure/fs/Loggers.d.ts +14 -0
- package/dist/infrastructure/fs/Loggers.js +18 -0
- package/dist/infrastructure/fs/Loggers.js.map +1 -0
- package/dist/infrastructure/fs/PidFileLock.d.ts +40 -0
- package/dist/infrastructure/fs/PidFileLock.js +97 -0
- package/dist/infrastructure/fs/PidFileLock.js.map +1 -0
- package/dist/infrastructure/fs/ProjectIndexes.d.ts +8 -0
- package/dist/infrastructure/fs/ProjectIndexes.js +35 -0
- package/dist/infrastructure/fs/ProjectIndexes.js.map +1 -0
- package/dist/infrastructure/fs/ProjectMetadataStore.d.ts +42 -0
- package/dist/infrastructure/fs/ProjectMetadataStore.js +86 -0
- package/dist/infrastructure/fs/ProjectMetadataStore.js.map +1 -0
- package/dist/infrastructure/fs/ProjectRegistry.d.ts +25 -0
- package/dist/infrastructure/fs/ProjectRegistry.js +83 -0
- package/dist/infrastructure/fs/ProjectRegistry.js.map +1 -0
- package/dist/infrastructure/fs/StateDirectory.d.ts +28 -0
- package/dist/infrastructure/fs/StateDirectory.js +71 -0
- package/dist/infrastructure/fs/StateDirectory.js.map +1 -0
- package/dist/infrastructure/fs/Workspace.d.ts +25 -0
- package/dist/infrastructure/fs/Workspace.js +90 -0
- package/dist/infrastructure/fs/Workspace.js.map +1 -0
- package/dist/infrastructure/git/GitClient.d.ts +34 -0
- package/dist/infrastructure/git/GitClient.js +74 -0
- package/dist/infrastructure/git/GitClient.js.map +1 -0
- package/dist/infrastructure/lancedb/ChunkRepository.d.ts +38 -0
- package/dist/infrastructure/lancedb/ChunkRepository.js +166 -0
- package/dist/infrastructure/lancedb/ChunkRepository.js.map +1 -0
- package/dist/infrastructure/lancedb/DatabaseImporter.d.ts +22 -0
- package/dist/infrastructure/lancedb/DatabaseImporter.js +74 -0
- package/dist/infrastructure/lancedb/DatabaseImporter.js.map +1 -0
- package/dist/infrastructure/lancedb/FileManifestRepository.d.ts +34 -0
- package/dist/infrastructure/lancedb/FileManifestRepository.js +137 -0
- package/dist/infrastructure/lancedb/FileManifestRepository.js.map +1 -0
- package/dist/infrastructure/lancedb/IndexMaintenance.d.ts +53 -0
- package/dist/infrastructure/lancedb/IndexMaintenance.js +227 -0
- package/dist/infrastructure/lancedb/IndexMaintenance.js.map +1 -0
- package/dist/infrastructure/lancedb/LanceTables.d.ts +67 -0
- package/dist/infrastructure/lancedb/LanceTables.js +159 -0
- package/dist/infrastructure/lancedb/LanceTables.js.map +1 -0
- package/dist/{lib/native-tuning.js → infrastructure/lancedb/NativeTuning.js} +1 -1
- package/dist/infrastructure/lancedb/NativeTuning.js.map +1 -0
- package/dist/infrastructure/lancedb/RowReplication.d.ts +27 -0
- package/dist/infrastructure/lancedb/RowReplication.js +82 -0
- package/dist/infrastructure/lancedb/RowReplication.js.map +1 -0
- package/dist/infrastructure/lancedb/VectorIndexPolicy.d.ts +60 -0
- package/dist/infrastructure/lancedb/VectorIndexPolicy.js +72 -0
- package/dist/infrastructure/lancedb/VectorIndexPolicy.js.map +1 -0
- package/dist/infrastructure/p2p/IndexShare.d.ts +45 -0
- package/dist/infrastructure/p2p/IndexShare.js +160 -0
- package/dist/infrastructure/p2p/IndexShare.js.map +1 -0
- package/dist/infrastructure/p2p/PeerSwarm.d.ts +16 -0
- package/dist/infrastructure/p2p/PeerSwarm.js +41 -0
- package/dist/infrastructure/p2p/PeerSwarm.js.map +1 -0
- package/dist/infrastructure/p2p/SecureChannel.d.ts +60 -0
- package/dist/infrastructure/p2p/SecureChannel.js +71 -0
- package/dist/infrastructure/p2p/SecureChannel.js.map +1 -0
- package/dist/infrastructure/p2p/ShareCode.d.ts +25 -0
- package/dist/infrastructure/p2p/ShareCode.js +304 -0
- package/dist/infrastructure/p2p/ShareCode.js.map +1 -0
- package/dist/infrastructure/process/ProcessRegistry.d.ts +50 -0
- package/dist/infrastructure/process/ProcessRegistry.js +109 -0
- package/dist/infrastructure/process/ProcessRegistry.js.map +1 -0
- package/dist/infrastructure/treesitter/ChunkContextBuilder.d.ts +45 -0
- package/dist/infrastructure/treesitter/ChunkContextBuilder.js +159 -0
- package/dist/infrastructure/treesitter/ChunkContextBuilder.js.map +1 -0
- package/dist/infrastructure/treesitter/EmbeddedTreeSitterAssets.d.ts +8 -0
- package/dist/infrastructure/treesitter/EmbeddedTreeSitterAssets.js +12 -0
- package/dist/infrastructure/treesitter/EmbeddedTreeSitterAssets.js.map +1 -0
- package/dist/infrastructure/treesitter/LanguageCatalog.d.ts +30 -0
- package/dist/{lib/chunker/languages.js → infrastructure/treesitter/LanguageCatalog.js} +38 -29
- package/dist/infrastructure/treesitter/LanguageCatalog.js.map +1 -0
- package/dist/infrastructure/treesitter/SlidingWindowChunker.d.ts +15 -0
- package/dist/infrastructure/treesitter/SlidingWindowChunker.js +42 -0
- package/dist/infrastructure/treesitter/SlidingWindowChunker.js.map +1 -0
- package/dist/infrastructure/treesitter/TreeSitterChunker.d.ts +42 -0
- package/dist/infrastructure/treesitter/TreeSitterChunker.js +165 -0
- package/dist/infrastructure/treesitter/TreeSitterChunker.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +14 -72
- package/dist/mcp.js.map +1 -1
- package/dist/presentation/cli/Cli.d.ts +31 -0
- package/dist/presentation/cli/Cli.js +120 -0
- package/dist/presentation/cli/Cli.js.map +1 -0
- package/dist/presentation/cli/CliOptions.d.ts +18 -0
- package/dist/presentation/cli/CliOptions.js +25 -0
- package/dist/presentation/cli/CliOptions.js.map +1 -0
- package/dist/presentation/cli/CommandContext.d.ts +50 -0
- package/dist/presentation/cli/CommandContext.js +88 -0
- package/dist/presentation/cli/CommandContext.js.map +1 -0
- package/dist/presentation/cli/ConfigTemplate.d.ts +31 -0
- package/dist/presentation/cli/ConfigTemplate.js +83 -0
- package/dist/presentation/cli/ConfigTemplate.js.map +1 -0
- package/dist/presentation/cli/Renderer.d.ts +90 -0
- package/dist/presentation/cli/Renderer.js +290 -0
- package/dist/presentation/cli/Renderer.js.map +1 -0
- package/dist/presentation/cli/commands/AskCommand.d.ts +14 -0
- package/dist/presentation/cli/commands/AskCommand.js +48 -0
- package/dist/presentation/cli/commands/AskCommand.js.map +1 -0
- package/dist/presentation/cli/commands/CompletionsCommand.d.ts +18 -0
- package/dist/presentation/cli/commands/CompletionsCommand.js +96 -0
- package/dist/presentation/cli/commands/CompletionsCommand.js.map +1 -0
- package/dist/presentation/cli/commands/ConfigCommands.d.ts +56 -0
- package/dist/presentation/cli/commands/ConfigCommands.js +220 -0
- package/dist/presentation/cli/commands/ConfigCommands.js.map +1 -0
- package/dist/presentation/cli/commands/IndexCommand.d.ts +18 -0
- package/dist/presentation/cli/commands/IndexCommand.js +54 -0
- package/dist/presentation/cli/commands/IndexCommand.js.map +1 -0
- package/dist/presentation/cli/commands/ProjectsCommand.d.ts +48 -0
- package/dist/presentation/cli/commands/ProjectsCommand.js +240 -0
- package/dist/presentation/cli/commands/ProjectsCommand.js.map +1 -0
- package/dist/presentation/cli/commands/SearchCommand.d.ts +19 -0
- package/dist/presentation/cli/commands/SearchCommand.js +55 -0
- package/dist/presentation/cli/commands/SearchCommand.js.map +1 -0
- package/dist/presentation/cli/commands/ServerCommands.d.ts +13 -0
- package/dist/presentation/cli/commands/ServerCommands.js +40 -0
- package/dist/presentation/cli/commands/ServerCommands.js.map +1 -0
- package/dist/presentation/cli/commands/ShareCommands.d.ts +22 -0
- package/dist/presentation/cli/commands/ShareCommands.js +134 -0
- package/dist/presentation/cli/commands/ShareCommands.js.map +1 -0
- package/dist/presentation/cli/commands/StatusCommand.d.ts +15 -0
- package/dist/presentation/cli/commands/StatusCommand.js +53 -0
- package/dist/presentation/cli/commands/StatusCommand.js.map +1 -0
- package/dist/presentation/mcp/HitFormatter.d.ts +17 -0
- package/dist/presentation/mcp/HitFormatter.js +42 -0
- package/dist/presentation/mcp/HitFormatter.js.map +1 -0
- package/dist/presentation/mcp/IndexWatchController.d.ts +17 -0
- package/dist/presentation/mcp/IndexWatchController.js +31 -0
- package/dist/presentation/mcp/IndexWatchController.js.map +1 -0
- package/dist/presentation/mcp/LmgrepCore.d.ts +66 -0
- package/dist/presentation/mcp/LmgrepCore.js +178 -0
- package/dist/presentation/mcp/LmgrepCore.js.map +1 -0
- package/dist/presentation/mcp/McpServer.d.ts +18 -0
- package/dist/presentation/mcp/McpServer.js +63 -0
- package/dist/presentation/mcp/McpServer.js.map +1 -0
- package/dist/presentation/mcp/ToolDescriptions.d.ts +40 -0
- package/dist/presentation/mcp/ToolDescriptions.js +85 -0
- package/dist/presentation/mcp/ToolDescriptions.js.map +1 -0
- package/package.json +93 -89
- package/dist/lib/build.d.ts +0 -21
- package/dist/lib/build.js +0 -374
- package/dist/lib/build.js.map +0 -1
- package/dist/lib/chunker/context.d.ts +0 -21
- package/dist/lib/chunker/context.js +0 -131
- package/dist/lib/chunker/context.js.map +0 -1
- package/dist/lib/chunker/index.d.ts +0 -7
- package/dist/lib/chunker/index.js +0 -209
- package/dist/lib/chunker/index.js.map +0 -1
- package/dist/lib/chunker/languages.d.ts +0 -15
- package/dist/lib/chunker/languages.js.map +0 -1
- package/dist/lib/config.d.ts +0 -12
- package/dist/lib/config.js +0 -83
- package/dist/lib/config.js.map +0 -1
- package/dist/lib/embedder.d.ts +0 -65
- package/dist/lib/embedder.js +0 -236
- package/dist/lib/embedder.js.map +0 -1
- package/dist/lib/facet-session.d.ts +0 -44
- package/dist/lib/facet-session.js +0 -125
- package/dist/lib/facet-session.js.map +0 -1
- package/dist/lib/native-tuning.js.map +0 -1
- package/dist/lib/p2p.d.ts +0 -32
- package/dist/lib/p2p.js +0 -281
- package/dist/lib/p2p.js.map +0 -1
- package/dist/lib/providers.d.ts +0 -1
- package/dist/lib/providers.js +0 -41
- package/dist/lib/providers.js.map +0 -1
- package/dist/lib/repair.d.ts +0 -10
- package/dist/lib/repair.js +0 -57
- package/dist/lib/repair.js.map +0 -1
- package/dist/lib/scanner.d.ts +0 -34
- package/dist/lib/scanner.js +0 -242
- package/dist/lib/scanner.js.map +0 -1
- package/dist/lib/search-tool.d.ts +0 -55
- package/dist/lib/search-tool.js +0 -319
- package/dist/lib/search-tool.js.map +0 -1
- package/dist/lib/serve.d.ts +0 -11
- package/dist/lib/serve.js +0 -144
- package/dist/lib/serve.js.map +0 -1
- package/dist/lib/store.d.ts +0 -252
- package/dist/lib/store.js +0 -1216
- package/dist/lib/store.js.map +0 -1
- package/dist/lib/types.d.ts +0 -194
- package/dist/lib/types.js +0 -13
- package/dist/lib/types.js.map +0 -1
- package/dist/lib/vocab.d.ts +0 -20
- package/dist/lib/vocab.js +0 -275
- package/dist/lib/vocab.js.map +0 -1
- /package/dist/{lib/native-tuning.d.ts → infrastructure/lancedb/NativeTuning.d.ts} +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { ContentHash } from "../../domain/corpus/ContentHash.js";
|
|
2
|
+
import { FileManifest, } from "../../domain/corpus/SourceFile.js";
|
|
3
|
+
import { Branch } from "../../domain/project/Branch.js";
|
|
4
|
+
import { LanceTables, TableName } from "./LanceTables.js";
|
|
5
|
+
/**
|
|
6
|
+
* The branch-scoped file manifest in LanceDB.
|
|
7
|
+
*
|
|
8
|
+
* The current branch's manifest is cached because every search consults it to
|
|
9
|
+
* scope results, and re-reading it per query would dominate search latency.
|
|
10
|
+
* Anything that writes the manifest must {@link invalidate}.
|
|
11
|
+
*/
|
|
12
|
+
export class FileManifestRepository {
|
|
13
|
+
tables;
|
|
14
|
+
branch;
|
|
15
|
+
cached;
|
|
16
|
+
constructor(tables, branch) {
|
|
17
|
+
this.tables = tables;
|
|
18
|
+
this.branch = branch;
|
|
19
|
+
}
|
|
20
|
+
async current() {
|
|
21
|
+
const table = await this.tables.table(TableName.Files);
|
|
22
|
+
if (!table)
|
|
23
|
+
return FileManifest.empty();
|
|
24
|
+
const rows = await table
|
|
25
|
+
.query()
|
|
26
|
+
.where(`branch = '${this.branch.toSqlLiteral()}'`)
|
|
27
|
+
.select(["filePath", "fileHash"])
|
|
28
|
+
.toArray();
|
|
29
|
+
return FileManifest.fromEntries(rows.map((r) => [
|
|
30
|
+
r.filePath,
|
|
31
|
+
ContentHash.fromStored(r.fileHash),
|
|
32
|
+
]));
|
|
33
|
+
}
|
|
34
|
+
async branchVersions() {
|
|
35
|
+
if (this.cached)
|
|
36
|
+
return this.cached;
|
|
37
|
+
const table = await this.tables.table(TableName.Files);
|
|
38
|
+
if (!table)
|
|
39
|
+
return undefined;
|
|
40
|
+
this.cached = await this.current();
|
|
41
|
+
return this.cached;
|
|
42
|
+
}
|
|
43
|
+
invalidate() {
|
|
44
|
+
this.cached = undefined;
|
|
45
|
+
}
|
|
46
|
+
async upsert(entries) {
|
|
47
|
+
if (entries.length === 0)
|
|
48
|
+
return;
|
|
49
|
+
const records = entries.map((e) => ({
|
|
50
|
+
filePath: e.path,
|
|
51
|
+
fileHash: e.hash.toString(),
|
|
52
|
+
branch: this.branch.toString(),
|
|
53
|
+
}));
|
|
54
|
+
const { table, seeded } = await this.tables.tableOrCreate(TableName.Files, records);
|
|
55
|
+
if (seeded) {
|
|
56
|
+
this.invalidate();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Replace this branch's rows for these paths, leaving other branches'
|
|
60
|
+
// rows for the same paths untouched.
|
|
61
|
+
const paths = records.map((r) => r.filePath);
|
|
62
|
+
for (let i = 0; i < paths.length; i += LanceTables.FILTER_BATCH_SIZE) {
|
|
63
|
+
const batch = paths.slice(i, i + LanceTables.FILTER_BATCH_SIZE);
|
|
64
|
+
await table.delete(`branch = '${this.branch.toSqlLiteral()}' AND ${LanceTables.inFilter("filePath", batch)}`);
|
|
65
|
+
}
|
|
66
|
+
await table.add(records);
|
|
67
|
+
this.invalidate();
|
|
68
|
+
}
|
|
69
|
+
async deleteFiles(filePaths) {
|
|
70
|
+
const table = await this.tables.table(TableName.Files);
|
|
71
|
+
if (!table || filePaths.length === 0)
|
|
72
|
+
return;
|
|
73
|
+
for (let i = 0; i < filePaths.length; i += LanceTables.FILTER_BATCH_SIZE) {
|
|
74
|
+
const batch = filePaths.slice(i, i + LanceTables.FILTER_BATCH_SIZE);
|
|
75
|
+
await table.delete(`branch = '${this.branch.toSqlLiteral()}' AND ${LanceTables.inFilter("filePath", batch)}`);
|
|
76
|
+
}
|
|
77
|
+
this.invalidate();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Which of these file versions any branch has already indexed. A hit means
|
|
81
|
+
* the content is embedded, so the file can be registered on this branch
|
|
82
|
+
* without re-chunking it.
|
|
83
|
+
*/
|
|
84
|
+
async knownHashes(hashes) {
|
|
85
|
+
const table = await this.tables.table(TableName.Files);
|
|
86
|
+
if (!table || hashes.length === 0)
|
|
87
|
+
return new Set();
|
|
88
|
+
return LanceTables.selectIn(table, "fileHash", hashes.map((h) => h.toString()));
|
|
89
|
+
}
|
|
90
|
+
async allEntries() {
|
|
91
|
+
const table = await this.tables.table(TableName.Files);
|
|
92
|
+
if (!table)
|
|
93
|
+
return [];
|
|
94
|
+
const rows = await table.query().toArray();
|
|
95
|
+
return rows.map((r) => ({
|
|
96
|
+
filePath: r.filePath,
|
|
97
|
+
fileHash: ContentHash.fromStored(r.fileHash),
|
|
98
|
+
branch: Branch.of(r.branch),
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
async storedBranches() {
|
|
102
|
+
const table = await this.tables.table(TableName.Files);
|
|
103
|
+
if (!table)
|
|
104
|
+
return [];
|
|
105
|
+
const rows = await table.query().select(["branch"]).toArray();
|
|
106
|
+
return [...new Set(rows.map((r) => r.branch))];
|
|
107
|
+
}
|
|
108
|
+
async deleteBranch(branch) {
|
|
109
|
+
const table = await this.tables.table(TableName.Files);
|
|
110
|
+
if (!table)
|
|
111
|
+
return;
|
|
112
|
+
await table.delete(`branch = '${LanceTables.quote(branch)}'`);
|
|
113
|
+
this.invalidate();
|
|
114
|
+
}
|
|
115
|
+
/** Seed this branch's manifest from another's — used on a new branch. */
|
|
116
|
+
async copyFromBranch(sourceBranch) {
|
|
117
|
+
const table = await this.tables.table(TableName.Files);
|
|
118
|
+
if (!table)
|
|
119
|
+
return 0;
|
|
120
|
+
const rows = await table
|
|
121
|
+
.query()
|
|
122
|
+
.where(`branch = '${LanceTables.quote(sourceBranch)}'`)
|
|
123
|
+
.select(["filePath", "fileHash"])
|
|
124
|
+
.toArray();
|
|
125
|
+
if (rows.length === 0)
|
|
126
|
+
return 0;
|
|
127
|
+
const records = rows.map((r) => ({
|
|
128
|
+
filePath: r.filePath,
|
|
129
|
+
fileHash: r.fileHash,
|
|
130
|
+
branch: this.branch.toString(),
|
|
131
|
+
}));
|
|
132
|
+
await table.add(records);
|
|
133
|
+
this.invalidate();
|
|
134
|
+
return records.length;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=FileManifestRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileManifestRepository.js","sourceRoot":"","sources":["../../../src/infrastructure/lancedb/FileManifestRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { FileManifestRepositoryPort } from "../../domain/ports/FileManifestRepositoryPort.js";
|
|
2
|
+
import type { DedupeReport, IndexMaintenancePort, OptimizeOptions, OptimizeReport, VectorIndexState } from "../../domain/ports/IndexMaintenancePort.js";
|
|
3
|
+
import { type LanceTables } from "./LanceTables.js";
|
|
4
|
+
/**
|
|
5
|
+
* Keeps the LanceDB tables compact and their ANN indexes current.
|
|
6
|
+
*
|
|
7
|
+
* Without a vector index LanceDB answers a search by brute force: it decodes
|
|
8
|
+
* every stored embedding to score it. At high dimensions that walks the whole
|
|
9
|
+
* table through memory per query, so peak RSS tracks index size roughly 1:1.
|
|
10
|
+
* IVF-PQ turns that into a handful of probes.
|
|
11
|
+
*
|
|
12
|
+
* Compaction matters for the same reason — small appends leave hundreds of
|
|
13
|
+
* fragments, each carrying its own decode buffers.
|
|
14
|
+
*/
|
|
15
|
+
export declare class IndexMaintenance implements IndexMaintenancePort {
|
|
16
|
+
private readonly tables;
|
|
17
|
+
private readonly manifest;
|
|
18
|
+
/** Tables holding embeddings, and therefore wanting a vector index. */
|
|
19
|
+
private static readonly VECTOR_TABLES;
|
|
20
|
+
constructor(tables: LanceTables, manifest: FileManifestRepositoryPort);
|
|
21
|
+
/**
|
|
22
|
+
* Cheap and idempotent when there is nothing to do, so it is safe to call
|
|
23
|
+
* after every build.
|
|
24
|
+
*/
|
|
25
|
+
optimize(options?: OptimizeOptions): Promise<OptimizeReport>;
|
|
26
|
+
/**
|
|
27
|
+
* What `lmgrep compact` runs: the same work as {@link optimize} but
|
|
28
|
+
* unconditional, plus compaction of the files table (which holds no
|
|
29
|
+
* embeddings, so it never needs a vector index).
|
|
30
|
+
*/
|
|
31
|
+
compact(): Promise<OptimizeReport>;
|
|
32
|
+
/**
|
|
33
|
+
* Remove tables no longer part of the schema.
|
|
34
|
+
*
|
|
35
|
+
* Databases built before faceting was removed still carry a `vocab` table
|
|
36
|
+
* holding one embedding per corpus term — nothing reads it now, and at
|
|
37
|
+
* full embedding width that is real disk. Dropping it here means users
|
|
38
|
+
* reclaim the space by running the command they already run.
|
|
39
|
+
*/
|
|
40
|
+
private dropLegacyTables;
|
|
41
|
+
private optimizeTable;
|
|
42
|
+
/**
|
|
43
|
+
* Remove rows that should not be there: exact id duplicates (from
|
|
44
|
+
* concurrent unlocked indexing) and chunks whose file version no branch
|
|
45
|
+
* references any more. Survivors are rewritten into a fresh table, which is
|
|
46
|
+
* also what reclaims the disk the dropped rows held.
|
|
47
|
+
*/
|
|
48
|
+
dedupe(): Promise<DedupeReport>;
|
|
49
|
+
vectorIndexState(): Promise<VectorIndexState>;
|
|
50
|
+
reset(): Promise<void>;
|
|
51
|
+
/** Arrow rows carry typed arrays; LanceDB needs plain values to re-infer a schema. */
|
|
52
|
+
private toPlainRow;
|
|
53
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { Index } from "@lancedb/lancedb";
|
|
2
|
+
import { ChunkRepository } from "./ChunkRepository.js";
|
|
3
|
+
import { TableName } from "./LanceTables.js";
|
|
4
|
+
import { VectorIndexPolicy } from "./VectorIndexPolicy.js";
|
|
5
|
+
/**
|
|
6
|
+
* Keeps the LanceDB tables compact and their ANN indexes current.
|
|
7
|
+
*
|
|
8
|
+
* Without a vector index LanceDB answers a search by brute force: it decodes
|
|
9
|
+
* every stored embedding to score it. At high dimensions that walks the whole
|
|
10
|
+
* table through memory per query, so peak RSS tracks index size roughly 1:1.
|
|
11
|
+
* IVF-PQ turns that into a handful of probes.
|
|
12
|
+
*
|
|
13
|
+
* Compaction matters for the same reason — small appends leave hundreds of
|
|
14
|
+
* fragments, each carrying its own decode buffers.
|
|
15
|
+
*/
|
|
16
|
+
export class IndexMaintenance {
|
|
17
|
+
tables;
|
|
18
|
+
manifest;
|
|
19
|
+
/** Tables holding embeddings, and therefore wanting a vector index. */
|
|
20
|
+
static VECTOR_TABLES = [TableName.Chunks];
|
|
21
|
+
constructor(tables, manifest) {
|
|
22
|
+
this.tables = tables;
|
|
23
|
+
this.manifest = manifest;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Cheap and idempotent when there is nothing to do, so it is safe to call
|
|
27
|
+
* after every build.
|
|
28
|
+
*/
|
|
29
|
+
async optimize(options = {}) {
|
|
30
|
+
const report = { tables: [] };
|
|
31
|
+
for (const name of IndexMaintenance.VECTOR_TABLES) {
|
|
32
|
+
const table = await this.tables.table(name);
|
|
33
|
+
if (!table)
|
|
34
|
+
continue;
|
|
35
|
+
report.tables.push(await this.optimizeTable(name, table, options.force ?? false, options.create ?? false));
|
|
36
|
+
}
|
|
37
|
+
return report;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* What `lmgrep compact` runs: the same work as {@link optimize} but
|
|
41
|
+
* unconditional, plus compaction of the files table (which holds no
|
|
42
|
+
* embeddings, so it never needs a vector index).
|
|
43
|
+
*/
|
|
44
|
+
async compact() {
|
|
45
|
+
const report = await this.optimize({ force: true, create: true });
|
|
46
|
+
await this.dropLegacyTables(report);
|
|
47
|
+
const files = await this.tables.table(TableName.Files);
|
|
48
|
+
if (files) {
|
|
49
|
+
await files.optimize();
|
|
50
|
+
report.tables.push({
|
|
51
|
+
table: TableName.Files,
|
|
52
|
+
rows: await files.countRows(),
|
|
53
|
+
action: "optimized",
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return report;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Remove tables no longer part of the schema.
|
|
60
|
+
*
|
|
61
|
+
* Databases built before faceting was removed still carry a `vocab` table
|
|
62
|
+
* holding one embedding per corpus term — nothing reads it now, and at
|
|
63
|
+
* full embedding width that is real disk. Dropping it here means users
|
|
64
|
+
* reclaim the space by running the command they already run.
|
|
65
|
+
*/
|
|
66
|
+
async dropLegacyTables(report) {
|
|
67
|
+
const vocab = await this.tables.table(TableName.LegacyVocab);
|
|
68
|
+
if (!vocab)
|
|
69
|
+
return;
|
|
70
|
+
const rows = await vocab.countRows();
|
|
71
|
+
await this.tables.dropTable(TableName.LegacyVocab);
|
|
72
|
+
report.tables.push({
|
|
73
|
+
table: TableName.LegacyVocab,
|
|
74
|
+
rows,
|
|
75
|
+
action: "dropped",
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
async optimizeTable(name, table, force, create) {
|
|
79
|
+
const rows = await table.countRows();
|
|
80
|
+
// listIndices reports the columns each index covers, so this stays
|
|
81
|
+
// correct if a scalar index is ever added alongside the vector one.
|
|
82
|
+
const indices = await table.listIndices();
|
|
83
|
+
const vectorIndex = indices.find((i) => i.columns.includes("vector"));
|
|
84
|
+
if (!vectorIndex) {
|
|
85
|
+
// The size guard is not overridable. `force` means "don't wait for
|
|
86
|
+
// the tail to grow", not "cluster a table with too few vectors to
|
|
87
|
+
// cluster" — IVF-PQ on a small table trains empty partitions and
|
|
88
|
+
// degrades recall for no memory saving.
|
|
89
|
+
if (rows < VectorIndexPolicy.MIN_ROWS_FOR_ANN) {
|
|
90
|
+
return { table: name, rows, action: "skipped-small" };
|
|
91
|
+
}
|
|
92
|
+
if (!create) {
|
|
93
|
+
return { table: name, rows, action: "needs-index" };
|
|
94
|
+
}
|
|
95
|
+
// numPartitions and numSubVectors are left to LanceDB, which
|
|
96
|
+
// derives them from row count and dimensionality. Hard-coding them
|
|
97
|
+
// would only reproduce that rule for dimensions already seen.
|
|
98
|
+
await table.createIndex("vector", {
|
|
99
|
+
config: Index.ivfPq({
|
|
100
|
+
distanceType: VectorIndexPolicy.DISTANCE_TYPE,
|
|
101
|
+
}),
|
|
102
|
+
replace: true,
|
|
103
|
+
});
|
|
104
|
+
await table.optimize();
|
|
105
|
+
return { table: name, rows, action: "created" };
|
|
106
|
+
}
|
|
107
|
+
const stats = await table.indexStats(vectorIndex.name);
|
|
108
|
+
const unindexed = stats?.numUnindexedRows ?? 0;
|
|
109
|
+
const indexed = stats?.numIndexedRows ?? 0;
|
|
110
|
+
const tolerated = Math.max(VectorIndexPolicy.UNINDEXED_REINDEX_FLOOR, Math.floor(indexed * VectorIndexPolicy.UNINDEXED_REINDEX_RATIO));
|
|
111
|
+
if (!force && unindexed <= tolerated) {
|
|
112
|
+
return { table: name, rows, action: "up-to-date", unindexed };
|
|
113
|
+
}
|
|
114
|
+
// optimize() both compacts fragments and folds the unindexed tail into
|
|
115
|
+
// the existing index — no retraining from scratch.
|
|
116
|
+
await table.optimize();
|
|
117
|
+
return { table: name, rows, action: "optimized", unindexed };
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Remove rows that should not be there: exact id duplicates (from
|
|
121
|
+
* concurrent unlocked indexing) and chunks whose file version no branch
|
|
122
|
+
* references any more. Survivors are rewritten into a fresh table, which is
|
|
123
|
+
* also what reclaims the disk the dropped rows held.
|
|
124
|
+
*/
|
|
125
|
+
async dedupe() {
|
|
126
|
+
const table = await this.tables.table(TableName.Chunks);
|
|
127
|
+
if (!table) {
|
|
128
|
+
return { before: 0, after: 0, duplicateIds: 0, staleVersions: 0 };
|
|
129
|
+
}
|
|
130
|
+
const before = await table.countRows();
|
|
131
|
+
// (filePath, fileHash) pairs any branch still references.
|
|
132
|
+
const referenced = new Map();
|
|
133
|
+
for (const entry of await this.manifest.allEntries()) {
|
|
134
|
+
const set = referenced.get(entry.filePath) ?? new Set();
|
|
135
|
+
set.add(entry.fileHash.toString());
|
|
136
|
+
referenced.set(entry.filePath, set);
|
|
137
|
+
}
|
|
138
|
+
const kept = [];
|
|
139
|
+
const seenIds = new Set();
|
|
140
|
+
let duplicateIds = 0;
|
|
141
|
+
let staleVersions = 0;
|
|
142
|
+
const total = before;
|
|
143
|
+
const BATCH = 2000;
|
|
144
|
+
for (let offset = 0; offset < total; offset += BATCH) {
|
|
145
|
+
const rows = await table.query().limit(BATCH).offset(offset).toArray();
|
|
146
|
+
if (rows.length === 0)
|
|
147
|
+
break;
|
|
148
|
+
for (const row of rows) {
|
|
149
|
+
const id = row.id;
|
|
150
|
+
if (seenIds.has(id)) {
|
|
151
|
+
duplicateIds++;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
seenIds.add(id);
|
|
155
|
+
const filePath = row.filePath;
|
|
156
|
+
const fileHash = row.fileHash ?? "";
|
|
157
|
+
// "" is the legacy wildcard — never stale.
|
|
158
|
+
if (fileHash !== "" && !referenced.get(filePath)?.has(fileHash)) {
|
|
159
|
+
staleVersions++;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
kept.push(this.toPlainRow(row));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (duplicateIds + staleVersions === 0) {
|
|
166
|
+
return { before, after: before, duplicateIds, staleVersions };
|
|
167
|
+
}
|
|
168
|
+
await this.tables.dropTable(TableName.Chunks);
|
|
169
|
+
if (kept.length > 0) {
|
|
170
|
+
const { table: rebuilt, seeded } = await this.tables.tableOrCreate(TableName.Chunks, kept);
|
|
171
|
+
if (!seeded)
|
|
172
|
+
await rebuilt.add(kept);
|
|
173
|
+
}
|
|
174
|
+
return { before, after: kept.length, duplicateIds, staleVersions };
|
|
175
|
+
}
|
|
176
|
+
async vectorIndexState() {
|
|
177
|
+
const table = await this.tables.table(TableName.Chunks);
|
|
178
|
+
if (!table) {
|
|
179
|
+
return { rows: 0, built: false, unindexed: 0, worthBuilding: false };
|
|
180
|
+
}
|
|
181
|
+
const rows = await table.countRows();
|
|
182
|
+
const index = (await table.listIndices()).find((i) => i.columns.includes("vector"));
|
|
183
|
+
if (!index) {
|
|
184
|
+
return {
|
|
185
|
+
rows,
|
|
186
|
+
built: false,
|
|
187
|
+
unindexed: rows,
|
|
188
|
+
worthBuilding: rows >= VectorIndexPolicy.MIN_ROWS_FOR_ANN,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const stats = await table.indexStats(index.name);
|
|
192
|
+
return {
|
|
193
|
+
rows,
|
|
194
|
+
built: true,
|
|
195
|
+
unindexed: stats?.numUnindexedRows ?? 0,
|
|
196
|
+
worthBuilding: true,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
async reset() {
|
|
200
|
+
for (const name of [
|
|
201
|
+
TableName.Chunks,
|
|
202
|
+
TableName.Files,
|
|
203
|
+
TableName.LegacyVocab,
|
|
204
|
+
]) {
|
|
205
|
+
await this.tables.dropTable(name);
|
|
206
|
+
}
|
|
207
|
+
this.manifest.invalidate();
|
|
208
|
+
}
|
|
209
|
+
/** Arrow rows carry typed arrays; LanceDB needs plain values to re-infer a schema. */
|
|
210
|
+
toPlainRow(row) {
|
|
211
|
+
const chunk = ChunkRepository.rowToChunk(row);
|
|
212
|
+
return {
|
|
213
|
+
id: row.id,
|
|
214
|
+
filePath: chunk.location.filePath,
|
|
215
|
+
startLine: chunk.location.startLine,
|
|
216
|
+
endLine: chunk.location.endLine,
|
|
217
|
+
type: chunk.type,
|
|
218
|
+
name: chunk.name,
|
|
219
|
+
content: chunk.content,
|
|
220
|
+
context: chunk.context,
|
|
221
|
+
hash: chunk.hash.toString(),
|
|
222
|
+
fileHash: chunk.fileVersion.toStored(),
|
|
223
|
+
vector: Array.from(row.vector),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=IndexMaintenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndexMaintenance.js","sourceRoot":"","sources":["../../../src/infrastructure/lancedb/IndexMaintenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type Table } from "@lancedb/lancedb";
|
|
2
|
+
import type { Branch } from "../../domain/project/Branch.js";
|
|
3
|
+
/**
|
|
4
|
+
* Table names inside a LanceDB database directory.
|
|
5
|
+
*
|
|
6
|
+
* A const object rather than a `const enum`: const enums are erased at emit,
|
|
7
|
+
* so importing one across modules compiles but can vanish at runtime.
|
|
8
|
+
*/
|
|
9
|
+
export declare const TableName: {
|
|
10
|
+
readonly Chunks: "chunks";
|
|
11
|
+
readonly Files: "files";
|
|
12
|
+
/**
|
|
13
|
+
* Written by the removed faceting feature. Nothing reads it; it is listed
|
|
14
|
+
* so maintenance can drop it and give the disk back.
|
|
15
|
+
*/
|
|
16
|
+
readonly LegacyVocab: "vocab";
|
|
17
|
+
};
|
|
18
|
+
export type TableName = (typeof TableName)[keyof typeof TableName];
|
|
19
|
+
/**
|
|
20
|
+
* Shared access to one LanceDB database: connecting, opening tables lazily,
|
|
21
|
+
* and running the schema backfills legacy databases need.
|
|
22
|
+
*
|
|
23
|
+
* The repositories share an instance so they share a connection — LanceDB
|
|
24
|
+
* connections are per-directory and opening several would multiply the native
|
|
25
|
+
* runtime's memory.
|
|
26
|
+
*/
|
|
27
|
+
export declare class LanceTables {
|
|
28
|
+
readonly path: string;
|
|
29
|
+
private readonly branch;
|
|
30
|
+
/**
|
|
31
|
+
* Predicates are built by string interpolation, so batches are kept small
|
|
32
|
+
* enough that no single filter grows unreasonably long.
|
|
33
|
+
*/
|
|
34
|
+
static readonly FILTER_BATCH_SIZE = 50;
|
|
35
|
+
private db;
|
|
36
|
+
private readonly open;
|
|
37
|
+
constructor(path: string, branch: Branch);
|
|
38
|
+
private connection;
|
|
39
|
+
/** Open a table, or undefined when the database has never held it. */
|
|
40
|
+
table(name: TableName): Promise<Table | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* Open a table, creating it from `seed` rows when it does not exist.
|
|
43
|
+
* `seeded` says whether creation consumed the rows, so the caller knows not
|
|
44
|
+
* to insert them a second time.
|
|
45
|
+
*/
|
|
46
|
+
tableOrCreate(name: TableName, seed: Record<string, unknown>[]): Promise<{
|
|
47
|
+
table: Table;
|
|
48
|
+
seeded: boolean;
|
|
49
|
+
}>;
|
|
50
|
+
tableNames(): Promise<string[]>;
|
|
51
|
+
dropTable(name: TableName): Promise<void>;
|
|
52
|
+
/** Forget cached handles so the next access re-opens and re-migrates. */
|
|
53
|
+
forget(name?: TableName): void;
|
|
54
|
+
close(): void;
|
|
55
|
+
/** `column IN ('a', 'b')`, with values single-quote escaped. */
|
|
56
|
+
static inFilter(column: string, values: readonly string[]): string;
|
|
57
|
+
static quote(value: string): string;
|
|
58
|
+
/** Run `column IN (...)` deletes in batches small enough for one predicate. */
|
|
59
|
+
static deleteIn(table: Table, column: string, values: readonly string[]): Promise<void>;
|
|
60
|
+
/** Run a batched `column IN (...)` select, collecting one column's values. */
|
|
61
|
+
static selectIn(table: Table, column: string, values: readonly string[]): Promise<Set<string>>;
|
|
62
|
+
/**
|
|
63
|
+
* Backfill columns that legacy databases predate. Both are additive and
|
|
64
|
+
* idempotent — a table that already has the column is left alone.
|
|
65
|
+
*/
|
|
66
|
+
private migrate;
|
|
67
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { mkdirSync } from "node:fs";
|
|
2
|
+
import { connect } from "@lancedb/lancedb";
|
|
3
|
+
/**
|
|
4
|
+
* Table names inside a LanceDB database directory.
|
|
5
|
+
*
|
|
6
|
+
* A const object rather than a `const enum`: const enums are erased at emit,
|
|
7
|
+
* so importing one across modules compiles but can vanish at runtime.
|
|
8
|
+
*/
|
|
9
|
+
export const TableName = {
|
|
10
|
+
Chunks: "chunks",
|
|
11
|
+
Files: "files",
|
|
12
|
+
/**
|
|
13
|
+
* Written by the removed faceting feature. Nothing reads it; it is listed
|
|
14
|
+
* so maintenance can drop it and give the disk back.
|
|
15
|
+
*/
|
|
16
|
+
LegacyVocab: "vocab",
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Shared access to one LanceDB database: connecting, opening tables lazily,
|
|
20
|
+
* and running the schema backfills legacy databases need.
|
|
21
|
+
*
|
|
22
|
+
* The repositories share an instance so they share a connection — LanceDB
|
|
23
|
+
* connections are per-directory and opening several would multiply the native
|
|
24
|
+
* runtime's memory.
|
|
25
|
+
*/
|
|
26
|
+
export class LanceTables {
|
|
27
|
+
path;
|
|
28
|
+
branch;
|
|
29
|
+
/**
|
|
30
|
+
* Predicates are built by string interpolation, so batches are kept small
|
|
31
|
+
* enough that no single filter grows unreasonably long.
|
|
32
|
+
*/
|
|
33
|
+
static FILTER_BATCH_SIZE = 50;
|
|
34
|
+
db;
|
|
35
|
+
open = new Map();
|
|
36
|
+
constructor(path, branch) {
|
|
37
|
+
this.path = path;
|
|
38
|
+
this.branch = branch;
|
|
39
|
+
}
|
|
40
|
+
async connection() {
|
|
41
|
+
if (this.db)
|
|
42
|
+
return this.db;
|
|
43
|
+
mkdirSync(this.path, { recursive: true });
|
|
44
|
+
this.db = await connect(this.path);
|
|
45
|
+
return this.db;
|
|
46
|
+
}
|
|
47
|
+
/** Open a table, or undefined when the database has never held it. */
|
|
48
|
+
async table(name) {
|
|
49
|
+
const cached = this.open.get(name);
|
|
50
|
+
if (cached)
|
|
51
|
+
return cached;
|
|
52
|
+
const conn = await this.connection();
|
|
53
|
+
const names = await conn.tableNames();
|
|
54
|
+
if (!names.includes(name))
|
|
55
|
+
return undefined;
|
|
56
|
+
const table = await conn.openTable(name);
|
|
57
|
+
await this.migrate(name, table);
|
|
58
|
+
this.open.set(name, table);
|
|
59
|
+
return table;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Open a table, creating it from `seed` rows when it does not exist.
|
|
63
|
+
* `seeded` says whether creation consumed the rows, so the caller knows not
|
|
64
|
+
* to insert them a second time.
|
|
65
|
+
*/
|
|
66
|
+
async tableOrCreate(name, seed) {
|
|
67
|
+
const existing = await this.table(name);
|
|
68
|
+
if (existing)
|
|
69
|
+
return { table: existing, seeded: false };
|
|
70
|
+
const conn = await this.connection();
|
|
71
|
+
const created = await conn.createTable(name, seed);
|
|
72
|
+
this.open.set(name, created);
|
|
73
|
+
return { table: created, seeded: true };
|
|
74
|
+
}
|
|
75
|
+
async tableNames() {
|
|
76
|
+
return (await this.connection()).tableNames();
|
|
77
|
+
}
|
|
78
|
+
async dropTable(name) {
|
|
79
|
+
const conn = await this.connection();
|
|
80
|
+
const names = await conn.tableNames();
|
|
81
|
+
if (names.includes(name))
|
|
82
|
+
await conn.dropTable(name);
|
|
83
|
+
this.open.delete(name);
|
|
84
|
+
}
|
|
85
|
+
/** Forget cached handles so the next access re-opens and re-migrates. */
|
|
86
|
+
forget(name) {
|
|
87
|
+
if (name)
|
|
88
|
+
this.open.delete(name);
|
|
89
|
+
else
|
|
90
|
+
this.open.clear();
|
|
91
|
+
}
|
|
92
|
+
close() {
|
|
93
|
+
this.open.clear();
|
|
94
|
+
this.db = undefined;
|
|
95
|
+
}
|
|
96
|
+
/** `column IN ('a', 'b')`, with values single-quote escaped. */
|
|
97
|
+
static inFilter(column, values) {
|
|
98
|
+
const escaped = values.map((v) => `'${v.replace(/'/g, "''")}'`);
|
|
99
|
+
return `${column} IN (${escaped.join(", ")})`;
|
|
100
|
+
}
|
|
101
|
+
static quote(value) {
|
|
102
|
+
return value.replace(/'/g, "''");
|
|
103
|
+
}
|
|
104
|
+
/** Run `column IN (...)` deletes in batches small enough for one predicate. */
|
|
105
|
+
static async deleteIn(table, column, values) {
|
|
106
|
+
for (let i = 0; i < values.length; i += LanceTables.FILTER_BATCH_SIZE) {
|
|
107
|
+
const batch = values.slice(i, i + LanceTables.FILTER_BATCH_SIZE);
|
|
108
|
+
await table.delete(LanceTables.inFilter(column, batch));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Run a batched `column IN (...)` select, collecting one column's values. */
|
|
112
|
+
static async selectIn(table, column, values) {
|
|
113
|
+
const found = new Set();
|
|
114
|
+
for (let i = 0; i < values.length; i += LanceTables.FILTER_BATCH_SIZE) {
|
|
115
|
+
const batch = values.slice(i, i + LanceTables.FILTER_BATCH_SIZE);
|
|
116
|
+
const rows = await table
|
|
117
|
+
.query()
|
|
118
|
+
.where(LanceTables.inFilter(column, batch))
|
|
119
|
+
.select([column])
|
|
120
|
+
.toArray();
|
|
121
|
+
for (const r of rows)
|
|
122
|
+
found.add(r[column]);
|
|
123
|
+
}
|
|
124
|
+
return found;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Backfill columns that legacy databases predate. Both are additive and
|
|
128
|
+
* idempotent — a table that already has the column is left alone.
|
|
129
|
+
*/
|
|
130
|
+
async migrate(name, table) {
|
|
131
|
+
if (name === TableName.Files) {
|
|
132
|
+
// Pre branch-scoping `files` tables have no `branch` column. Fill it
|
|
133
|
+
// with the current branch so branch-filtered queries keep working.
|
|
134
|
+
const schema = await table.schema();
|
|
135
|
+
if (schema.fields.some((f) => f.name === "branch"))
|
|
136
|
+
return;
|
|
137
|
+
await table.addColumns([
|
|
138
|
+
{
|
|
139
|
+
name: "branch",
|
|
140
|
+
valueSql: `CAST('${LanceTables.quote(this.branch.toString())}' AS STRING)`,
|
|
141
|
+
},
|
|
142
|
+
]);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (name === TableName.Chunks) {
|
|
146
|
+
// Pre version-scoping `chunks` tables have no `fileHash`. Fill it
|
|
147
|
+
// with "" — treated as a wildcard at search time, so legacy chunks
|
|
148
|
+
// keep appearing until their file is re-indexed and gets a real
|
|
149
|
+
// version hash.
|
|
150
|
+
const schema = await table.schema();
|
|
151
|
+
if (schema.fields.some((f) => f.name === "fileHash"))
|
|
152
|
+
return;
|
|
153
|
+
await table.addColumns([
|
|
154
|
+
{ name: "fileHash", valueSql: `CAST('' AS STRING)` },
|
|
155
|
+
]);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=LanceTables.js.map
|