@@ -6,6 +6,7 @@ import { IVectorStore } from "../interfaces/vector-store"
66import { Payload , VectorStoreSearchResult } from "../interfaces"
77import { DEFAULT_MAX_SEARCH_RESULTS , DEFAULT_SEARCH_MIN_SCORE } from "../constants"
88import { t } from "../../../i18n"
9+ import { getCurrentBranch , sanitizeBranchName } from "../../../utils/git"
910
1011/**
1112 * Qdrant implementation of the vector store interface
@@ -15,9 +16,11 @@ export class QdrantVectorStore implements IVectorStore {
1516 private readonly DISTANCE_METRIC = "Cosine"
1617
1718 private client : QdrantClient
18- private readonly collectionName : string
19+ private collectionName : string
1920 private readonly qdrantUrl : string = "http://localhost:6333"
2021 private readonly workspacePath : string
22+ private readonly branchIsolationEnabled : boolean
23+ private currentBranch : string | null = null
2124
2225 // Lazy collection creation flag
2326 private _collectionEnsured = false
@@ -29,23 +32,22 @@ export class QdrantVectorStore implements IVectorStore {
2932 * @param url Optional URL to the Qdrant server
3033 * @param vectorSize Size of the embedding vectors
3134 * @param apiKey Optional API key for Qdrant authentication
32- * @param branchIsolationEnabled Whether to include branch name in collection naming
33- * @param currentBranch Current Git branch name (used when branchIsolationEnabled is true)
35+ * @param branchIsolationEnabled Whether to use branch-specific collections
3436 */
3537 constructor (
3638 workspacePath : string ,
3739 url : string ,
3840 vectorSize : number ,
3941 apiKey ?: string ,
40- branchIsolationEnabled ?: boolean ,
41- currentBranch ?: string ,
42+ branchIsolationEnabled : boolean = false ,
4243 ) {
4344 // Parse the URL to determine the appropriate QdrantClient configuration
4445 const parsedUrl = this . parseQdrantUrl ( url )
4546
4647 // Store the resolved URL for our property
4748 this . qdrantUrl = parsedUrl
4849 this . workspacePath = workspacePath
50+ this . branchIsolationEnabled = branchIsolationEnabled
4951
5052 try {
5153 const urlObj = new URL ( parsedUrl )
@@ -92,34 +94,12 @@ export class QdrantVectorStore implements IVectorStore {
9294 } )
9395 }
9496
95- // Generate collection name from workspace path
97+ // Generate base collection name from workspace path
9698 const hash = createHash ( "sha256" ) . update ( workspacePath ) . digest ( "hex" )
9799 this . vectorSize = vectorSize
98100
99- // If branch isolation is enabled and we have a branch name, include it in the collection name
100- if ( branchIsolationEnabled && currentBranch ) {
101- const sanitizedBranch = this . sanitizeBranchName ( currentBranch )
102- this . collectionName = `ws-${ hash . substring ( 0 , 16 ) } -br-${ sanitizedBranch } `
103- } else {
104- this . collectionName = `ws-${ hash . substring ( 0 , 16 ) } `
105- }
106- }
107-
108- /**
109- * Sanitizes a Git branch name for use in Qdrant collection naming
110- * @param branch The branch name to sanitize
111- * @returns A sanitized branch name safe for collection naming
112- */
113- private sanitizeBranchName ( branch : string ) : string {
114- // Replace invalid characters with hyphens, collapse multiple hyphens, limit length
115- return (
116- branch
117- . replace ( / [ ^ a - z A - Z 0 - 9 _ - ] / g, "-" ) // Replace invalid chars with hyphens
118- . replace ( / - - + / g, "-" ) // Collapse multiple hyphens
119- . replace ( / ^ - + | - + $ / g, "" ) // Remove leading/trailing hyphens
120- . substring ( 0 , 50 ) // Limit length to 50 characters
121- . toLowerCase ( ) || "default"
122- ) // Fallback to 'default' if empty after sanitization
101+ // Base collection name (will be updated dynamically if branch isolation is enabled)
102+ this . collectionName = `ws-${ hash . substring ( 0 , 16 ) } `
123103 }
124104
125105 /**
@@ -267,6 +247,11 @@ export class QdrantVectorStore implements IVectorStore {
267247 * @throws {Error } If vector dimension mismatch cannot be resolved
268248 */
269249 async initialize ( ) : Promise < boolean > {
250+ // Update collection name based on current branch if branch isolation is enabled
251+ if ( this . branchIsolationEnabled ) {
252+ await this . updateCollectionNameForBranch ( )
253+ }
254+
270255 try {
271256 // Use shared helper to create or validate collection
272257 const created = await this . _createOrValidateCollection ( )
@@ -418,6 +403,11 @@ export class QdrantVectorStore implements IVectorStore {
418403 // Create and store the ensure promise
419404 this . _ensurePromise = ( async ( ) => {
420405 try {
406+ // Update collection name based on current branch if branch isolation is enabled
407+ if ( this . branchIsolationEnabled ) {
408+ await this . updateCollectionNameForBranch ( )
409+ }
410+
421411 // Use shared helper to create or validate collection
422412 await this . _createOrValidateCollection ( )
423413
@@ -701,4 +691,37 @@ export class QdrantVectorStore implements IVectorStore {
701691 const collectionInfo = await this . getCollectionInfo ( )
702692 return collectionInfo !== null
703693 }
694+
695+ /**
696+ * Updates the collection name based on the current Git branch
697+ * Only called when branch isolation is enabled
698+ */
699+ private async updateCollectionNameForBranch ( ) : Promise < void > {
700+ const branch = await getCurrentBranch ( this . workspacePath )
701+
702+ // Generate base collection name
703+ const hash = createHash ( "sha256" ) . update ( this . workspacePath ) . digest ( "hex" )
704+ let collectionName = `ws-${ hash . substring ( 0 , 16 ) } `
705+
706+ if ( branch ) {
707+ // Sanitize branch name for use in collection name
708+ const sanitizedBranch = sanitizeBranchName ( branch )
709+ collectionName = `${ collectionName } -br-${ sanitizedBranch } `
710+ this . currentBranch = branch
711+ } else {
712+ // Detached HEAD or not a git repo - use workspace-only collection
713+ this . currentBranch = null
714+ }
715+
716+ // Update the collection name
717+ this . collectionName = collectionName
718+ }
719+
720+ /**
721+ * Gets the current branch being used for the collection
722+ * @returns The current branch name or null if not using branch isolation
723+ */
724+ public getCurrentBranch ( ) : string | null {
725+ return this . branchIsolationEnabled ? this . currentBranch : null
726+ }
704727}
0 commit comments