@liendev/core 0.20.1 → 0.22.0

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.
Files changed (99) hide show
  1. package/README.md +10 -26
  2. package/dist/config/global-config.d.ts +37 -0
  3. package/dist/config/global-config.d.ts.map +1 -0
  4. package/dist/config/global-config.js +160 -0
  5. package/dist/config/global-config.js.map +1 -0
  6. package/dist/config/merge.js +1 -1
  7. package/dist/config/merge.js.map +1 -1
  8. package/dist/config/schema.d.ts +8 -1
  9. package/dist/config/schema.d.ts.map +1 -1
  10. package/dist/config/schema.js +2 -2
  11. package/dist/config/schema.js.map +1 -1
  12. package/dist/config/service.d.ts +2 -25
  13. package/dist/config/service.d.ts.map +1 -1
  14. package/dist/config/service.js +4 -79
  15. package/dist/config/service.js.map +1 -1
  16. package/dist/constants.d.ts +0 -1
  17. package/dist/constants.d.ts.map +1 -1
  18. package/dist/constants.js +0 -3
  19. package/dist/constants.js.map +1 -1
  20. package/dist/index.d.ts +20 -8
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +25 -9
  23. package/dist/index.js.map +1 -1
  24. package/dist/indexer/ast/chunker.d.ts +2 -0
  25. package/dist/indexer/ast/chunker.d.ts.map +1 -1
  26. package/dist/indexer/ast/chunker.js +13 -7
  27. package/dist/indexer/ast/chunker.js.map +1 -1
  28. package/dist/indexer/change-detector.d.ts +2 -3
  29. package/dist/indexer/change-detector.d.ts.map +1 -1
  30. package/dist/indexer/change-detector.js +19 -34
  31. package/dist/indexer/change-detector.js.map +1 -1
  32. package/dist/indexer/chunk-batch-processor.d.ts +2 -2
  33. package/dist/indexer/chunk-batch-processor.d.ts.map +1 -1
  34. package/dist/indexer/chunk-batch-processor.js.map +1 -1
  35. package/dist/indexer/chunker.d.ts +2 -0
  36. package/dist/indexer/chunker.d.ts.map +1 -1
  37. package/dist/indexer/chunker.js +9 -5
  38. package/dist/indexer/chunker.js.map +1 -1
  39. package/dist/indexer/incremental.d.ts +4 -4
  40. package/dist/indexer/incremental.d.ts.map +1 -1
  41. package/dist/indexer/incremental.js +35 -23
  42. package/dist/indexer/incremental.js.map +1 -1
  43. package/dist/indexer/index.d.ts +3 -1
  44. package/dist/indexer/index.d.ts.map +1 -1
  45. package/dist/indexer/index.js +109 -47
  46. package/dist/indexer/index.js.map +1 -1
  47. package/dist/indexer/json-template-chunker.d.ts +4 -1
  48. package/dist/indexer/json-template-chunker.d.ts.map +1 -1
  49. package/dist/indexer/json-template-chunker.js +3 -1
  50. package/dist/indexer/json-template-chunker.js.map +1 -1
  51. package/dist/indexer/liquid-chunker.d.ts +4 -1
  52. package/dist/indexer/liquid-chunker.d.ts.map +1 -1
  53. package/dist/indexer/liquid-chunker.js +16 -14
  54. package/dist/indexer/liquid-chunker.js.map +1 -1
  55. package/dist/indexer/progress-tracker.d.ts +3 -1
  56. package/dist/indexer/progress-tracker.d.ts.map +1 -1
  57. package/dist/indexer/progress-tracker.js +8 -2
  58. package/dist/indexer/progress-tracker.js.map +1 -1
  59. package/dist/indexer/types.d.ts +22 -0
  60. package/dist/indexer/types.d.ts.map +1 -1
  61. package/dist/insights/complexity-analyzer.d.ts +6 -5
  62. package/dist/insights/complexity-analyzer.d.ts.map +1 -1
  63. package/dist/insights/complexity-analyzer.js +33 -14
  64. package/dist/insights/complexity-analyzer.js.map +1 -1
  65. package/dist/test/helpers/mock-embeddings.d.ts +12 -0
  66. package/dist/test/helpers/mock-embeddings.d.ts.map +1 -0
  67. package/dist/test/helpers/mock-embeddings.js +43 -0
  68. package/dist/test/helpers/mock-embeddings.js.map +1 -0
  69. package/dist/test/helpers/test-db.d.ts +21 -0
  70. package/dist/test/helpers/test-db.d.ts.map +1 -0
  71. package/dist/test/helpers/test-db.js +48 -0
  72. package/dist/test/helpers/test-db.js.map +1 -0
  73. package/dist/vectordb/factory.d.ts +15 -0
  74. package/dist/vectordb/factory.d.ts.map +1 -0
  75. package/dist/vectordb/factory.js +117 -0
  76. package/dist/vectordb/factory.js.map +1 -0
  77. package/dist/vectordb/qdrant-payload-mapper.d.ts +80 -0
  78. package/dist/vectordb/qdrant-payload-mapper.d.ts.map +1 -0
  79. package/dist/vectordb/qdrant-payload-mapper.js +129 -0
  80. package/dist/vectordb/qdrant-payload-mapper.js.map +1 -0
  81. package/dist/vectordb/qdrant.d.ts +201 -0
  82. package/dist/vectordb/qdrant.d.ts.map +1 -0
  83. package/dist/vectordb/qdrant.js +659 -0
  84. package/dist/vectordb/qdrant.js.map +1 -0
  85. package/dist/vectordb/types.d.ts +26 -1
  86. package/dist/vectordb/types.d.ts.map +1 -1
  87. package/package.json +2 -1
  88. package/dist/config/loader.d.ts +0 -12
  89. package/dist/config/loader.d.ts.map +0 -1
  90. package/dist/config/loader.js +0 -46
  91. package/dist/config/loader.js.map +0 -1
  92. package/dist/config/migration-manager.d.ts +0 -46
  93. package/dist/config/migration-manager.d.ts.map +0 -1
  94. package/dist/config/migration-manager.js +0 -119
  95. package/dist/config/migration-manager.js.map +0 -1
  96. package/dist/config/migration.d.ts +0 -20
  97. package/dist/config/migration.d.ts.map +0 -1
  98. package/dist/config/migration.js +0 -155
  99. package/dist/config/migration.js.map +0 -1
@@ -0,0 +1,117 @@
1
+ import { VectorDB } from './lancedb.js';
2
+ import { QdrantDB } from './qdrant.js';
3
+ import { loadGlobalConfig, extractOrgIdFromGit } from '../config/global-config.js';
4
+ import { getCurrentBranch, getCurrentCommit } from '../git/utils.js';
5
+ /**
6
+ * Validate that a VectorDB instance has the required methods.
7
+ */
8
+ function validateVectorDBInterface(db) {
9
+ if (typeof db.initialize !== 'function') {
10
+ throw new Error('VectorDB instance missing initialize method');
11
+ }
12
+ }
13
+ /**
14
+ * Create a LanceDB instance.
15
+ */
16
+ async function createLanceDB(projectRoot) {
17
+ const db = new VectorDB(projectRoot);
18
+ validateVectorDBInterface(db);
19
+ return db;
20
+ }
21
+ /**
22
+ * Create a QdrantDB instance.
23
+ * Extracts orgId, branch, and commit from git repository.
24
+ */
25
+ async function createQdrantDB(projectRoot, config) {
26
+ if (!config.url) {
27
+ throw new Error('Qdrant backend requires qdrant.url in global config');
28
+ }
29
+ // Auto-detect orgId from git remote
30
+ const orgId = await extractOrgIdFromGit(projectRoot);
31
+ if (!orgId) {
32
+ throw new Error('Qdrant backend requires a git repository with a remote URL. ' +
33
+ 'Could not extract organization ID from git remote. ' +
34
+ 'Make sure your project is a git repo with a remote configured (e.g., origin).');
35
+ }
36
+ // Extract branch and commit from git (both are required for Qdrant isolation)
37
+ // Fail fast if git commands fail - branch/commit tracking is essential for data isolation
38
+ let branch;
39
+ let commitSha;
40
+ try {
41
+ [branch, commitSha] = await Promise.all([
42
+ getCurrentBranch(projectRoot),
43
+ getCurrentCommit(projectRoot),
44
+ ]);
45
+ }
46
+ catch (error) {
47
+ throw new Error('Qdrant backend requires a valid git branch and commit SHA for proper data isolation. ' +
48
+ 'Failed to detect current branch and/or commit from git. ' +
49
+ 'Ensure the repository is initialized, has at least one commit, and HEAD is not detached. ' +
50
+ `Original error: ${error instanceof Error ? error.message : String(error)}`);
51
+ }
52
+ // Validate that branch and commitSha are non-empty (fail-fast for invalid git state)
53
+ if (!branch || branch.trim().length === 0) {
54
+ throw new Error('Qdrant backend requires a valid git branch for proper data isolation. ' +
55
+ 'Current branch is empty or whitespace. ' +
56
+ 'Ensure the repository is on a valid branch (not in detached HEAD state).');
57
+ }
58
+ if (!commitSha || commitSha.trim().length === 0) {
59
+ throw new Error('Qdrant backend requires a valid git commit SHA for proper data isolation. ' +
60
+ 'Current commit SHA is empty or whitespace. ' +
61
+ 'Ensure the repository has at least one commit.');
62
+ }
63
+ const db = new QdrantDB(config.url, config.apiKey, orgId, projectRoot, branch, commitSha);
64
+ validateVectorDBInterface(db);
65
+ return db;
66
+ }
67
+ /**
68
+ * Factory function to create a VectorDB instance based on global configuration.
69
+ *
70
+ * Selects the backend (LanceDB or Qdrant) based on global config.
71
+ * Defaults to LanceDB if no config is provided.
72
+ *
73
+ * For Qdrant backend, automatically detects orgId from git remote URL.
74
+ *
75
+ * @param projectRoot - Root directory of the project
76
+ * @returns VectorDBInterface instance (LanceDB or QdrantDB)
77
+ * @throws Error if Qdrant config is invalid or orgId cannot be detected
78
+ */
79
+ export async function createVectorDB(projectRoot) {
80
+ let globalConfig = null;
81
+ try {
82
+ globalConfig = await loadGlobalConfig();
83
+ }
84
+ catch (error) {
85
+ const errorMessage = error instanceof Error ? error.message : String(error);
86
+ // Check if this is a "file not found" error (expected) vs other errors (unexpected)
87
+ const isFileNotFound = errorMessage.includes('ENOENT') ||
88
+ errorMessage.includes('not found') ||
89
+ errorMessage.includes('does not exist');
90
+ if (isFileNotFound) {
91
+ // Expected: No config file exists, use default LanceDB (normal for CLI usage)
92
+ return await createLanceDB(projectRoot);
93
+ }
94
+ else {
95
+ // Unexpected: Config file exists but failed to load (syntax error, permissions, etc.)
96
+ // Fail hard - don't silently fall back to LanceDB
97
+ throw new Error('Failed to load global config file. Please check your config file for errors. ' +
98
+ `Error: ${errorMessage}`);
99
+ }
100
+ }
101
+ // Config loaded successfully - respect the backend choice
102
+ switch (globalConfig.backend) {
103
+ case 'qdrant':
104
+ if (!globalConfig.qdrant) {
105
+ throw new Error('Qdrant backend requires qdrant configuration in global config');
106
+ }
107
+ // Don't catch errors here - let Qdrant-specific errors propagate
108
+ // User explicitly configured Qdrant, so they should see configuration errors
109
+ return await createQdrantDB(projectRoot, globalConfig.qdrant);
110
+ case 'lancedb':
111
+ case undefined:
112
+ return await createLanceDB(projectRoot);
113
+ default:
114
+ throw new Error(`Unknown storage backend: ${globalConfig.backend}. Supported backends: 'lancedb', 'qdrant'`);
115
+ }
116
+ }
117
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/vectordb/factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { ChunkMetadata } from '../indexer/types.js';
2
+ /**
3
+ * Qdrant payload structure for storing chunk metadata.
4
+ *
5
+ * Note: Metrics (complexity, halstead) are always present as numbers.
6
+ * If missing in source metadata, they are stored as 0.
7
+ */
8
+ export interface QdrantPayload {
9
+ content: string;
10
+ file: string;
11
+ startLine: number;
12
+ endLine: number;
13
+ type: string;
14
+ language: string;
15
+ functionNames: string[];
16
+ classNames: string[];
17
+ interfaceNames: string[];
18
+ symbolName: string;
19
+ symbolType: string;
20
+ parentClass: string;
21
+ complexity: number;
22
+ cognitiveComplexity: number;
23
+ parameters: string[];
24
+ signature: string;
25
+ imports: string[];
26
+ halsteadVolume: number;
27
+ halsteadDifficulty: number;
28
+ halsteadEffort: number;
29
+ halsteadBugs: number;
30
+ orgId: string;
31
+ repoId: string;
32
+ branch: string;
33
+ commitSha: string;
34
+ }
35
+ /**
36
+ * Maps between ChunkMetadata and Qdrant payload format.
37
+ * Encapsulates the transformation logic for multi-tenant Qdrant storage.
38
+ */
39
+ export declare class QdrantPayloadMapper {
40
+ private orgId;
41
+ private repoId;
42
+ private branch;
43
+ private commitSha;
44
+ constructor(orgId: string, repoId: string, branch: string, commitSha: string);
45
+ /**
46
+ * Map metrics from metadata to payload format.
47
+ */
48
+ private mapMetrics;
49
+ /**
50
+ * Map symbols from metadata to payload format.
51
+ */
52
+ private mapSymbols;
53
+ /**
54
+ * Transform chunk metadata to Qdrant payload format.
55
+ */
56
+ toPayload(metadata: ChunkMetadata, content?: string): QdrantPayload;
57
+ /**
58
+ * Extract symbols from payload.
59
+ */
60
+ private extractSymbols;
61
+ /**
62
+ * Extract metrics from payload.
63
+ */
64
+ private extractMetrics;
65
+ /**
66
+ * Extract tracking info from payload.
67
+ *
68
+ * For legacy points indexed before branch/commit tracking was added, these
69
+ * fields may be missing. In that case they are returned as undefined and
70
+ * the points will not match branch/commitSha-based filters. Such data
71
+ * effectively becomes \"orphaned\" until it is re-indexed with tracking
72
+ * metadata, which is the expected migration path for old Qdrant data.
73
+ */
74
+ private extractTrackingInfo;
75
+ /**
76
+ * Transform Qdrant payload back to ChunkMetadata.
77
+ */
78
+ fromPayload(payload: Record<string, any>): ChunkMetadata;
79
+ }
80
+ //# sourceMappingURL=qdrant-payload-mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant-payload-mapper.d.ts","sourceRoot":"","sources":["../../src/vectordb/qdrant-payload-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IAEjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IAErB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;gBAHT,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM;IAG3B;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;OAEG;IACH,OAAO,CAAC,UAAU;IAclB;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,GAAE,MAAW,GAAG,aAAa;IAqBvE;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAWtB;;;;;;;;OAQG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,aAAa;CAkBzD"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Maps between ChunkMetadata and Qdrant payload format.
3
+ * Encapsulates the transformation logic for multi-tenant Qdrant storage.
4
+ */
5
+ export class QdrantPayloadMapper {
6
+ orgId;
7
+ repoId;
8
+ branch;
9
+ commitSha;
10
+ constructor(orgId, repoId, branch, commitSha) {
11
+ this.orgId = orgId;
12
+ this.repoId = repoId;
13
+ this.branch = branch;
14
+ this.commitSha = commitSha;
15
+ }
16
+ /**
17
+ * Map metrics from metadata to payload format.
18
+ */
19
+ mapMetrics(metadata) {
20
+ return {
21
+ complexity: metadata.complexity ?? 0,
22
+ cognitiveComplexity: metadata.cognitiveComplexity ?? 0,
23
+ halsteadVolume: metadata.halsteadVolume ?? 0,
24
+ halsteadDifficulty: metadata.halsteadDifficulty ?? 0,
25
+ halsteadEffort: metadata.halsteadEffort ?? 0,
26
+ halsteadBugs: metadata.halsteadBugs ?? 0,
27
+ };
28
+ }
29
+ /**
30
+ * Map symbols from metadata to payload format.
31
+ */
32
+ mapSymbols(metadata) {
33
+ return {
34
+ functionNames: metadata.symbols?.functions ?? [],
35
+ classNames: metadata.symbols?.classes ?? [],
36
+ interfaceNames: metadata.symbols?.interfaces ?? [],
37
+ symbolName: metadata.symbolName ?? '',
38
+ symbolType: metadata.symbolType ?? '',
39
+ parentClass: metadata.parentClass ?? '',
40
+ parameters: metadata.parameters ?? [],
41
+ signature: metadata.signature ?? '',
42
+ imports: metadata.imports ?? [],
43
+ };
44
+ }
45
+ /**
46
+ * Transform chunk metadata to Qdrant payload format.
47
+ */
48
+ toPayload(metadata, content = '') {
49
+ const trackingInfo = {
50
+ orgId: this.orgId,
51
+ repoId: this.repoId,
52
+ branch: this.branch,
53
+ commitSha: this.commitSha,
54
+ };
55
+ return {
56
+ content,
57
+ file: metadata.file,
58
+ startLine: metadata.startLine,
59
+ endLine: metadata.endLine,
60
+ type: metadata.type,
61
+ language: metadata.language,
62
+ ...this.mapSymbols(metadata),
63
+ ...this.mapMetrics(metadata),
64
+ ...trackingInfo,
65
+ };
66
+ }
67
+ /**
68
+ * Extract symbols from payload.
69
+ */
70
+ extractSymbols(payload) {
71
+ return {
72
+ functions: payload.functionNames ?? [],
73
+ classes: payload.classNames ?? [],
74
+ interfaces: payload.interfaceNames ?? [],
75
+ };
76
+ }
77
+ /**
78
+ * Extract metrics from payload.
79
+ */
80
+ extractMetrics(payload) {
81
+ return {
82
+ complexity: payload.complexity ?? undefined,
83
+ cognitiveComplexity: payload.cognitiveComplexity ?? undefined,
84
+ halsteadVolume: payload.halsteadVolume ?? undefined,
85
+ halsteadDifficulty: payload.halsteadDifficulty ?? undefined,
86
+ halsteadEffort: payload.halsteadEffort ?? undefined,
87
+ halsteadBugs: payload.halsteadBugs ?? undefined,
88
+ };
89
+ }
90
+ /**
91
+ * Extract tracking info from payload.
92
+ *
93
+ * For legacy points indexed before branch/commit tracking was added, these
94
+ * fields may be missing. In that case they are returned as undefined and
95
+ * the points will not match branch/commitSha-based filters. Such data
96
+ * effectively becomes \"orphaned\" until it is re-indexed with tracking
97
+ * metadata, which is the expected migration path for old Qdrant data.
98
+ */
99
+ extractTrackingInfo(payload) {
100
+ return {
101
+ repoId: payload.repoId ?? undefined,
102
+ orgId: payload.orgId ?? undefined,
103
+ branch: payload.branch ?? undefined,
104
+ commitSha: payload.commitSha ?? undefined,
105
+ };
106
+ }
107
+ /**
108
+ * Transform Qdrant payload back to ChunkMetadata.
109
+ */
110
+ fromPayload(payload) {
111
+ return {
112
+ file: payload.file,
113
+ startLine: payload.startLine,
114
+ endLine: payload.endLine,
115
+ type: payload.type,
116
+ language: payload.language,
117
+ symbols: this.extractSymbols(payload),
118
+ symbolName: payload.symbolName ?? undefined,
119
+ symbolType: payload.symbolType ?? undefined,
120
+ parentClass: payload.parentClass ?? undefined,
121
+ parameters: payload.parameters ?? undefined,
122
+ signature: payload.signature ?? undefined,
123
+ imports: payload.imports ?? undefined,
124
+ ...this.extractMetrics(payload),
125
+ ...this.extractTrackingInfo(payload),
126
+ };
127
+ }
128
+ }
129
+ //# sourceMappingURL=qdrant-payload-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant-payload-mapper.js","sourceRoot":"","sources":["../../src/vectordb/qdrant-payload-mapper.ts"],"names":[],"mappings":"AAyCA;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IAEpB;IACA;IACA;IACA;IAJV,YACU,KAAa,EACb,MAAc,EACd,MAAc,EACd,SAAiB;QAHjB,UAAK,GAAL,KAAK,CAAQ;QACb,WAAM,GAAN,MAAM,CAAQ;QACd,WAAM,GAAN,MAAM,CAAQ;QACd,cAAS,GAAT,SAAS,CAAQ;IACxB,CAAC;IAEJ;;OAEG;IACK,UAAU,CAAC,QAAuB;QACxC,OAAO;YACL,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,CAAC;YACpC,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB,IAAI,CAAC;YACtD,cAAc,EAAE,QAAQ,CAAC,cAAc,IAAI,CAAC;YAC5C,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB,IAAI,CAAC;YACpD,cAAc,EAAE,QAAQ,CAAC,cAAc,IAAI,CAAC;YAC5C,YAAY,EAAE,QAAQ,CAAC,YAAY,IAAI,CAAC;SACzC,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,UAAU,CAAC,QAAuB;QACxC,OAAO;YACL,aAAa,EAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,IAAI,EAAE;YAChD,UAAU,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE;YAC3C,cAAc,EAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE;YAClD,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,EAAE;YACrC,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,EAAE;YACrC,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,EAAE;YACvC,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,EAAE;YACrC,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,EAAE;YACnC,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,EAAE;SAChC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,QAAuB,EAAE,UAAkB,EAAE;QACrD,MAAM,YAAY,GAAG;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;QAEF,OAAO;YACL,OAAO;YACP,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAC5B,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAC5B,GAAG,YAAY;SAChB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,OAA4B;QACjD,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,aAAa,IAAI,EAAE;YACtC,OAAO,EAAE,OAAO,CAAC,UAAU,IAAI,EAAE;YACjC,UAAU,EAAE,OAAO,CAAC,cAAc,IAAI,EAAE;SACzC,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,OAA4B;QACjD,OAAO;YACL,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,SAAS;YAC3C,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,IAAI,SAAS;YAC7D,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,SAAS;YACnD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,SAAS;YAC3D,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,SAAS;YACnD,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,SAAS;SAChD,CAAC;IACJ,CAAC;IAED;;;;;;;;OAQG;IACK,mBAAmB,CAAC,OAA4B;QACtD,OAAO;YACL,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,SAAS;YACnC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;YACjC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,SAAS;YACnC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,SAAS;SAC1C,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,OAA4B;QACtC,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;YACrC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,SAAS;YAC3C,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,SAAS;YAC3C,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,SAAS;YAC7C,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,SAAS;YAC3C,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,SAAS;YACzC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,SAAS;YACrC,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;YAC/B,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC;SACrC,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,201 @@
1
+ import { SearchResult, VectorDBInterface } from './types.js';
2
+ import { ChunkMetadata } from '../indexer/types.js';
3
+ /**
4
+ * Validate filter options for buildBaseFilter.
5
+ *
6
+ * This is a separate function to enable unit testing of validation logic.
7
+ * The validations ensure that conflicting options are not used together.
8
+ *
9
+ * @param options - Filter options to validate
10
+ * @throws Error if conflicting options are detected
11
+ */
12
+ export declare function validateFilterOptions(options: {
13
+ repoIds?: string[];
14
+ branch?: string;
15
+ includeCurrentRepo?: boolean;
16
+ }): void;
17
+ /**
18
+ * QdrantDB implements VectorDBInterface using Qdrant vector database.
19
+ *
20
+ * Features:
21
+ * - Multi-tenant support via payload filtering (orgId/repoId)
22
+ * - Branch and commit isolation for PR workflows
23
+ * - Collection naming: `lien_org_{orgId}`
24
+ * - Cross-repo search by omitting repoId filter
25
+ * - Tenant isolation via orgId filtering
26
+ * - Point ID generation includes branch/commit to prevent collisions
27
+ *
28
+ * Data Isolation:
29
+ * All queries are filtered by orgId, repoId, branch, and commitSha by default.
30
+ * This ensures that different branches and commits have isolated data, preventing
31
+ * PRs from overwriting each other's indices. Use cross-repo methods (searchCrossRepo,
32
+ * scanCrossRepo) to query across repositories within an organization.
33
+ */
34
+ export declare class QdrantDB implements VectorDBInterface {
35
+ private client;
36
+ private collectionName;
37
+ private orgId;
38
+ private repoId;
39
+ private branch;
40
+ private commitSha;
41
+ private initialized;
42
+ readonly dbPath: string;
43
+ private lastVersionCheck;
44
+ private currentVersion;
45
+ private payloadMapper;
46
+ constructor(url: string, apiKey: string | undefined, orgId: string, projectRoot: string, branch: string, commitSha: string);
47
+ /**
48
+ * Extract repository identifier from project root.
49
+ * Uses project name + path hash for stable, unique identification.
50
+ */
51
+ private extractRepoId;
52
+ /**
53
+ * Generate a unique point ID from chunk metadata.
54
+ * Uses hash of file path + line range + branch + commitSha for stable identification.
55
+ * Includes branch/commit to prevent ID collisions across branches.
56
+ *
57
+ * **Hash Algorithm Choice:**
58
+ * Uses MD5 for performance and collision likelihood acceptable for this use case.
59
+ * - MD5 is deprecated for cryptographic purposes but suitable for non-security ID generation
60
+ * - Collision probability is extremely low: ~1 in 2^64 for random inputs
61
+ * - Input includes file path, line range, branch, and commit SHA, making collisions
62
+ * even less likely in practice
63
+ * - For typical codebases (thousands to hundreds of thousands of chunks), collision risk
64
+ * is negligible
65
+ * - If scaling to millions of chunks across many repos, consider upgrading to SHA-256
66
+ * for additional collision resistance (at ~10% performance cost)
67
+ */
68
+ private generatePointId;
69
+ /**
70
+ * Build base filter for Qdrant queries.
71
+ * Uses builder pattern to simplify filter construction.
72
+ *
73
+ * **Important constraints:**
74
+ * - `includeCurrentRepo` and `repoIds` are mutually exclusive.
75
+ * - `includeCurrentRepo` defaults to `true` when `undefined` (treats `undefined` as "enabled").
76
+ * - To use `repoIds` for cross-repo queries, you must explicitly pass `includeCurrentRepo: false`.
77
+ * - The `branch` parameter can only be used when `includeCurrentRepo` is explicitly `false`.
78
+ * When `includeCurrentRepo` is enabled (default), branch is automatically included via
79
+ * the current repo context (`addRepoContext`).
80
+ *
81
+ * @param options - Filter options
82
+ * @param options.includeCurrentRepo - Whether to filter by current repo context (default: true when undefined).
83
+ * Must be explicitly `false` to use `repoIds` or `branch` parameters.
84
+ * @param options.repoIds - Repository IDs to filter by (requires `includeCurrentRepo: false`).
85
+ * @param options.branch - Branch name to filter by (requires `includeCurrentRepo: false`).
86
+ * @returns Qdrant filter object
87
+ */
88
+ private buildBaseFilter;
89
+ /**
90
+ * Map Qdrant scroll results to SearchResult format.
91
+ *
92
+ * Note: Scroll/scan operations do not compute semantic similarity scores.
93
+ * For these results, score is always 0 and relevance is set to 'not_relevant'
94
+ * to indicate that the results are unscored (not that they are useless).
95
+ */
96
+ private mapScrollResults;
97
+ /**
98
+ * Execute a scroll query with error handling.
99
+ */
100
+ private executeScrollQuery;
101
+ initialize(): Promise<void>;
102
+ /**
103
+ * Validate batch input arrays have matching lengths.
104
+ */
105
+ private validateBatchInputs;
106
+ /**
107
+ * Prepare Qdrant points from vectors, metadatas, and contents.
108
+ */
109
+ private preparePoints;
110
+ insertBatch(vectors: Float32Array[], metadatas: ChunkMetadata[], contents: string[]): Promise<void>;
111
+ search(queryVector: Float32Array, limit?: number, _query?: string): Promise<SearchResult[]>;
112
+ /**
113
+ * Search across all repos in the organization (cross-repo search).
114
+ *
115
+ * - Omits repoId filter by default to enable true cross-repo queries.
116
+ * - When repoIds are provided, restricts results to those repositories only.
117
+ * - When branch is omitted, returns chunks from all branches and commits
118
+ * (including historical PR branches and stale commits).
119
+ * - When branch is provided, filters by branch name only and still returns
120
+ * chunks from all commits on that branch across the selected repos.
121
+ *
122
+ * This is a low-level primitive for cross-repo augmentation. Higher-level
123
+ * workflows (e.g. \"latest commit only\") should be built on top of this API.
124
+ *
125
+ * @param queryVector - Query vector for semantic search
126
+ * @param limit - Maximum number of results to return (default: 5)
127
+ * @param options - Optional search options
128
+ * @param options.repoIds - Repository IDs to filter by (optional)
129
+ * @param options.branch - Branch name to filter by (optional)
130
+ */
131
+ searchCrossRepo(queryVector: Float32Array, limit?: number, options?: {
132
+ repoIds?: string[];
133
+ branch?: string;
134
+ }): Promise<SearchResult[]>;
135
+ scanWithFilter(options: {
136
+ language?: string;
137
+ pattern?: string;
138
+ limit?: number;
139
+ }): Promise<SearchResult[]>;
140
+ scanAll(options?: {
141
+ language?: string;
142
+ pattern?: string;
143
+ }): Promise<SearchResult[]>;
144
+ /**
145
+ * Scan with filter across all repos in the organization (cross-repo).
146
+ *
147
+ * - Omits repoId filter by default to enable true cross-repo scans.
148
+ * - When repoIds are provided, restricts results to those repositories only.
149
+ * - When branch is omitted, returns chunks from all branches and commits
150
+ * (including historical PR branches and stale commits).
151
+ * - When branch is provided, filters by branch name only and still returns
152
+ * chunks from all commits on that branch across the selected repos.
153
+ *
154
+ * Like searchCrossRepo, this is a low-level primitive. Higher-level behavior
155
+ * such as \"latest commit only\" should be implemented in orchestrating code.
156
+ */
157
+ scanCrossRepo(options: {
158
+ language?: string;
159
+ pattern?: string;
160
+ limit?: number;
161
+ repoIds?: string[];
162
+ branch?: string;
163
+ }): Promise<SearchResult[]>;
164
+ querySymbols(options: {
165
+ language?: string;
166
+ pattern?: string;
167
+ symbolType?: 'function' | 'class' | 'interface';
168
+ limit?: number;
169
+ }): Promise<SearchResult[]>;
170
+ clear(): Promise<void>;
171
+ /**
172
+ * Clear all data for a specific branch (all commits).
173
+ *
174
+ * Qdrant-only helper: this is not part of the generic VectorDBInterface and
175
+ * is intended for cloud/PR workflows where multiple commits exist per branch.
176
+ * LanceDB and other backends do not implement this method.
177
+ *
178
+ * @param branch - Branch name to clear (defaults to current branch)
179
+ */
180
+ clearBranch(branch?: string): Promise<void>;
181
+ deleteByFile(filepath: string): Promise<void>;
182
+ updateFile(filepath: string, vectors: Float32Array[], metadatas: ChunkMetadata[], contents: string[]): Promise<void>;
183
+ hasData(): Promise<boolean>;
184
+ /**
185
+ * Get the collection name (useful for debugging).
186
+ */
187
+ getCollectionName(): string;
188
+ /**
189
+ * Get the organization ID.
190
+ */
191
+ getOrgId(): string;
192
+ /**
193
+ * Get the repository ID.
194
+ */
195
+ getRepoId(): string;
196
+ checkVersion(): Promise<boolean>;
197
+ reconnect(): Promise<void>;
198
+ getCurrentVersion(): number;
199
+ getVersionDate(): string;
200
+ }
201
+ //# sourceMappingURL=qdrant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant.d.ts","sourceRoot":"","sources":["../../src/vectordb/qdrant.ts"],"names":[],"mappings":"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"}