@zilliz/claude-context-core 0.1.11 → 0.1.12
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 +2 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/context.d.ts +17 -2
- package/dist/context.d.ts.map +1 -1
- package/dist/context.ignore-patterns.test.js +145 -14
- package/dist/context.ignore-patterns.test.js.map +1 -1
- package/dist/context.js +102 -29
- package/dist/context.js.map +1 -1
- package/dist/context.splitter.test.d.ts +2 -0
- package/dist/context.splitter.test.d.ts.map +1 -0
- package/dist/context.splitter.test.js +202 -0
- package/dist/context.splitter.test.js.map +1 -0
- package/dist/sync/synchronizer.d.ts +1 -0
- package/dist/sync/synchronizer.d.ts.map +1 -1
- package/dist/sync/synchronizer.js +32 -33
- package/dist/sync/synchronizer.js.map +1 -1
- package/dist/vectordb/__tests__/milvus-query-filter.test.d.ts +9 -0
- package/dist/vectordb/__tests__/milvus-query-filter.test.d.ts.map +1 -0
- package/dist/vectordb/__tests__/milvus-query-filter.test.js +90 -0
- package/dist/vectordb/__tests__/milvus-query-filter.test.js.map +1 -0
- package/package.json +1 -1
package/dist/context.d.ts
CHANGED
|
@@ -41,6 +41,11 @@ export declare class Context {
|
|
|
41
41
|
* Get supported extensions
|
|
42
42
|
*/
|
|
43
43
|
getSupportedExtensions(): string[];
|
|
44
|
+
/**
|
|
45
|
+
* Get supported extensions for the current operation without mutating
|
|
46
|
+
* the Context's persistent extension list.
|
|
47
|
+
*/
|
|
48
|
+
getEffectiveSupportedExtensions(additionalExtensions?: string[]): string[];
|
|
44
49
|
/**
|
|
45
50
|
* Get ignore patterns
|
|
46
51
|
*/
|
|
@@ -81,6 +86,9 @@ export declare class Context {
|
|
|
81
86
|
* @param codebasePath Codebase root path
|
|
82
87
|
* @param progressCallback Optional progress callback function
|
|
83
88
|
* @param forceReindex Whether to recreate the collection even if it exists
|
|
89
|
+
* @param additionalIgnorePatterns Request-scoped ignore patterns
|
|
90
|
+
* @param additionalSupportedExtensions Request-scoped file extensions
|
|
91
|
+
* @param requestSplitter Request-scoped splitter for this indexing run
|
|
84
92
|
* @returns Indexing statistics
|
|
85
93
|
*/
|
|
86
94
|
indexCodebase(codebasePath: string, progressCallback?: (progress: {
|
|
@@ -88,7 +96,7 @@ export declare class Context {
|
|
|
88
96
|
current: number;
|
|
89
97
|
total: number;
|
|
90
98
|
percentage: number;
|
|
91
|
-
}) => void, forceReindex?: boolean, additionalIgnorePatterns?: string[]): Promise<{
|
|
99
|
+
}) => void, forceReindex?: boolean, additionalIgnorePatterns?: string[], additionalSupportedExtensions?: string[], requestSplitter?: Splitter): Promise<{
|
|
92
100
|
indexedFiles: number;
|
|
93
101
|
totalChunks: number;
|
|
94
102
|
status: 'completed' | 'limit_reached';
|
|
@@ -98,7 +106,7 @@ export declare class Context {
|
|
|
98
106
|
current: number;
|
|
99
107
|
total: number;
|
|
100
108
|
percentage: number;
|
|
101
|
-
}) => void): Promise<{
|
|
109
|
+
}) => void, additionalIgnorePatterns?: string[], additionalSupportedExtensions?: string[], requestSplitter?: Splitter): Promise<{
|
|
102
110
|
added: number;
|
|
103
111
|
removed: number;
|
|
104
112
|
modified: number;
|
|
@@ -112,6 +120,11 @@ export declare class Context {
|
|
|
112
120
|
* @param threshold Similarity threshold
|
|
113
121
|
*/
|
|
114
122
|
semanticSearch(codebasePath: string, query: string, topK?: number, threshold?: number, filterExpr?: string): Promise<SemanticSearchResult[]>;
|
|
123
|
+
/**
|
|
124
|
+
* Deduplicate search results by file + line range overlap.
|
|
125
|
+
* Keeps higher-scored result when two results from the same file overlap >50%.
|
|
126
|
+
*/
|
|
127
|
+
private deduplicateResults;
|
|
115
128
|
/**
|
|
116
129
|
* Check if index exists for codebase
|
|
117
130
|
* @param codebasePath Codebase path to check
|
|
@@ -241,6 +254,7 @@ export declare class Context {
|
|
|
241
254
|
* @returns True if pattern matches
|
|
242
255
|
*/
|
|
243
256
|
private isPatternMatch;
|
|
257
|
+
private matchesDirectoryPattern;
|
|
244
258
|
/**
|
|
245
259
|
* Simple glob matching supporting * wildcard
|
|
246
260
|
* @param text Text to test
|
|
@@ -261,6 +275,7 @@ export declare class Context {
|
|
|
261
275
|
* @returns Array of custom ignore patterns
|
|
262
276
|
*/
|
|
263
277
|
private getCustomIgnorePatternsFromEnv;
|
|
278
|
+
private normalizeExtensions;
|
|
264
279
|
/**
|
|
265
280
|
* Add custom extensions (from MCP or other sources) without replacing existing ones
|
|
266
281
|
* @param customExtensions Array of custom extensions to add
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,QAAQ,EAGX,MAAM,YAAY,CAAC;AACpB,OAAO,EACH,SAAS,EAGZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACH,cAAc,EAMjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAK/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAkEvD,MAAM,WAAW,aAAa;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,YAAY,CAAC,EAAE,QAAQ,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,qBAAa,OAAO;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAO;IAEzD,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAW;IAC/B,OAAO,CAAC,mBAAmB,CAAW;IACtC,OAAO,CAAC,kBAAkB,CAAW;IACrC,OAAO,CAAC,cAAc,CAAW;IACjC,OAAO,CAAC,sBAAsB,CAAC,CAAS;IACxC,OAAO,CAAC,0BAA0B,CAAqB;IACvD,OAAO,CAAC,aAAa,CAAuC;gBAEhD,MAAM,GAAE,aAAkB;IAmDtC;;OAEG;IACH,YAAY,IAAI,SAAS;IAIzB;;OAEG;IACH,iBAAiB,IAAI,cAAc;IAInC;;OAEG;IACH,eAAe,IAAI,QAAQ;IAI3B;;OAEG;IACH,sBAAsB,IAAI,MAAM,EAAE;IAIlC;;OAEG;IACH,iBAAiB,IAAI,MAAM,EAAE;IAI7B;;OAEG;IACH,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAIjD;;OAEG;IACH,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,GAAG,IAAI;IAI7E;;OAEG;IACG,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlE;;;OAGG;IACG,0BAA0B,CAAC,YAAY,EAAE,MAAM,EAAE,wBAAwB,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIlH;;OAEG;IACG,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE;;OAEG;IACH,OAAO,CAAC,WAAW;IAQnB;;OAEG;IACI,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAuBtD,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,4BAA4B;IAyBpC
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,31 +37,72 @@ const fs = __importStar(require("fs/promises"));
|
|
|
37
37
|
const os = __importStar(require("os"));
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
39
|
const context_1 = require("./context");
|
|
40
|
+
const embedding_1 = require("./embedding");
|
|
41
|
+
const synchronizer_1 = require("./sync/synchronizer");
|
|
42
|
+
class TestEmbedding extends embedding_1.Embedding {
|
|
43
|
+
constructor() {
|
|
44
|
+
super(...arguments);
|
|
45
|
+
this.maxTokens = 8192;
|
|
46
|
+
}
|
|
47
|
+
async detectDimension() {
|
|
48
|
+
return 3;
|
|
49
|
+
}
|
|
50
|
+
async embed(text) {
|
|
51
|
+
return { vector: [1, 0, 0], dimension: 3 };
|
|
52
|
+
}
|
|
53
|
+
async embedBatch(texts) {
|
|
54
|
+
return texts.map(() => ({ vector: [1, 0, 0], dimension: 3 }));
|
|
55
|
+
}
|
|
56
|
+
getDimension() {
|
|
57
|
+
return 3;
|
|
58
|
+
}
|
|
59
|
+
getProvider() {
|
|
60
|
+
return 'test';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
class TestSplitter {
|
|
64
|
+
async split(code, language, filePath) {
|
|
65
|
+
return [{
|
|
66
|
+
content: code,
|
|
67
|
+
metadata: {
|
|
68
|
+
startLine: 1,
|
|
69
|
+
endLine: 1,
|
|
70
|
+
language,
|
|
71
|
+
filePath,
|
|
72
|
+
},
|
|
73
|
+
}];
|
|
74
|
+
}
|
|
75
|
+
setChunkSize() { }
|
|
76
|
+
setChunkOverlap() { }
|
|
77
|
+
}
|
|
40
78
|
const createVectorDatabase = () => ({
|
|
41
|
-
createCollection: jest.fn(),
|
|
42
|
-
createHybridCollection: jest.fn(),
|
|
43
|
-
dropCollection: jest.fn(),
|
|
44
|
-
hasCollection: jest.fn(),
|
|
45
|
-
listCollections: jest.fn(),
|
|
46
|
-
insert: jest.fn(),
|
|
47
|
-
insertHybrid: jest.fn(),
|
|
48
|
-
search: jest.fn(),
|
|
49
|
-
hybridSearch: jest.fn(),
|
|
50
|
-
delete: jest.fn(),
|
|
51
|
-
query: jest.fn(),
|
|
52
|
-
getCollectionDescription: jest.fn(),
|
|
53
|
-
checkCollectionLimit: jest.fn(),
|
|
54
|
-
getCollectionRowCount: jest.fn(),
|
|
79
|
+
createCollection: jest.fn().mockResolvedValue(undefined),
|
|
80
|
+
createHybridCollection: jest.fn().mockResolvedValue(undefined),
|
|
81
|
+
dropCollection: jest.fn().mockResolvedValue(undefined),
|
|
82
|
+
hasCollection: jest.fn().mockResolvedValue(false),
|
|
83
|
+
listCollections: jest.fn().mockResolvedValue([]),
|
|
84
|
+
insert: jest.fn().mockResolvedValue(undefined),
|
|
85
|
+
insertHybrid: jest.fn().mockResolvedValue(undefined),
|
|
86
|
+
search: jest.fn().mockResolvedValue([]),
|
|
87
|
+
hybridSearch: jest.fn().mockResolvedValue([]),
|
|
88
|
+
delete: jest.fn().mockResolvedValue(undefined),
|
|
89
|
+
query: jest.fn().mockResolvedValue([]),
|
|
90
|
+
getCollectionDescription: jest.fn().mockResolvedValue(''),
|
|
91
|
+
checkCollectionLimit: jest.fn().mockResolvedValue(true),
|
|
92
|
+
getCollectionRowCount: jest.fn().mockResolvedValue(0),
|
|
55
93
|
});
|
|
56
94
|
describe('Context ignore pattern isolation', () => {
|
|
57
95
|
let tempRoot;
|
|
58
96
|
let originalHome;
|
|
97
|
+
let originalHybridMode;
|
|
59
98
|
beforeEach(async () => {
|
|
60
99
|
tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'claude-context-ignore-'));
|
|
61
100
|
const homeDir = path.join(tempRoot, 'home');
|
|
62
101
|
await fs.mkdir(homeDir, { recursive: true });
|
|
63
102
|
originalHome = process.env.HOME;
|
|
103
|
+
originalHybridMode = process.env.HYBRID_MODE;
|
|
64
104
|
process.env.HOME = homeDir;
|
|
105
|
+
process.env.HYBRID_MODE = 'false';
|
|
65
106
|
});
|
|
66
107
|
afterEach(async () => {
|
|
67
108
|
if (originalHome === undefined) {
|
|
@@ -70,6 +111,12 @@ describe('Context ignore pattern isolation', () => {
|
|
|
70
111
|
else {
|
|
71
112
|
process.env.HOME = originalHome;
|
|
72
113
|
}
|
|
114
|
+
if (originalHybridMode === undefined) {
|
|
115
|
+
delete process.env.HYBRID_MODE;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
process.env.HYBRID_MODE = originalHybridMode;
|
|
119
|
+
}
|
|
73
120
|
await fs.rm(tempRoot, { recursive: true, force: true });
|
|
74
121
|
});
|
|
75
122
|
it('does not leak file-based ignore patterns between codebases', async () => {
|
|
@@ -93,5 +140,89 @@ describe('Context ignore pattern isolation', () => {
|
|
|
93
140
|
const withoutRequestIgnores = await context.getEffectiveIgnorePatterns(project);
|
|
94
141
|
expect(withoutRequestIgnores).not.toContain('*.txt');
|
|
95
142
|
});
|
|
143
|
+
it('does not leak request custom extensions into persistent supported extensions', () => {
|
|
144
|
+
const context = new context_1.Context({ vectorDatabase: createVectorDatabase() });
|
|
145
|
+
const withRequestExtensions = context.getEffectiveSupportedExtensions(['foo']);
|
|
146
|
+
expect(withRequestExtensions).toContain('.foo');
|
|
147
|
+
const withoutRequestExtensions = context.getSupportedExtensions();
|
|
148
|
+
expect(withoutRequestExtensions).not.toContain('.foo');
|
|
149
|
+
});
|
|
150
|
+
it('does not leak request custom extensions between codebase indexes', async () => {
|
|
151
|
+
const projectA = path.join(tempRoot, 'project-a');
|
|
152
|
+
const projectB = path.join(tempRoot, 'project-b');
|
|
153
|
+
await fs.mkdir(projectA);
|
|
154
|
+
await fs.mkdir(projectB);
|
|
155
|
+
await fs.writeFile(path.join(projectA, 'a.foo'), 'project a custom file');
|
|
156
|
+
await fs.writeFile(path.join(projectB, 'b.foo'), 'project b custom file');
|
|
157
|
+
const vectorDatabase = createVectorDatabase();
|
|
158
|
+
const context = new context_1.Context({
|
|
159
|
+
embedding: new TestEmbedding(),
|
|
160
|
+
vectorDatabase,
|
|
161
|
+
codeSplitter: new TestSplitter(),
|
|
162
|
+
});
|
|
163
|
+
await context.indexCodebase(projectA, undefined, false, [], ['foo']);
|
|
164
|
+
expect(vectorDatabase.insert).toHaveBeenCalledTimes(1);
|
|
165
|
+
expect(vectorDatabase.insert.mock.calls[0][1][0].relativePath).toBe('a.foo');
|
|
166
|
+
vectorDatabase.insert.mockClear();
|
|
167
|
+
await context.indexCodebase(projectB);
|
|
168
|
+
expect(vectorDatabase.insert).not.toHaveBeenCalled();
|
|
169
|
+
});
|
|
170
|
+
it('uses request options when recreating a synchronizer for change indexing', async () => {
|
|
171
|
+
const project = path.join(tempRoot, 'project-with-options');
|
|
172
|
+
await fs.mkdir(project);
|
|
173
|
+
await fs.writeFile(path.join(project, 'custom.foo'), 'custom extension file');
|
|
174
|
+
await fs.writeFile(path.join(project, 'ignored.ts'), 'ignored by request pattern');
|
|
175
|
+
const context = new context_1.Context({ vectorDatabase: createVectorDatabase() });
|
|
176
|
+
try {
|
|
177
|
+
await context.reindexByChange(project, undefined, ['*.ts'], ['foo']);
|
|
178
|
+
const collectionName = context.getCollectionName(project);
|
|
179
|
+
const synchronizer = context.getSynchronizers().get(collectionName);
|
|
180
|
+
expect(synchronizer).toBeDefined();
|
|
181
|
+
expect(synchronizer?.getFileHash('custom.foo')).toBeDefined();
|
|
182
|
+
expect(synchronizer?.getFileHash('ignored.ts')).toBeUndefined();
|
|
183
|
+
expect(context.getSupportedExtensions()).not.toContain('.foo');
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
await synchronizer_1.FileSynchronizer.deleteSnapshot(project);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
it('treats leading-slash directory ignore patterns as root-anchored and recursive during indexing', async () => {
|
|
190
|
+
const project = path.join(tempRoot, 'project');
|
|
191
|
+
await fs.mkdir(path.join(project, 'Library'), { recursive: true });
|
|
192
|
+
await fs.mkdir(path.join(project, 'src', 'Library'), { recursive: true });
|
|
193
|
+
await fs.writeFile(path.join(project, '.gitignore'), '/Library/\n');
|
|
194
|
+
await fs.writeFile(path.join(project, 'Library', 'generated.md'), 'root library should be ignored');
|
|
195
|
+
await fs.writeFile(path.join(project, 'src', 'Library', 'nested.md'), 'nested library should stay');
|
|
196
|
+
await fs.writeFile(path.join(project, 'src', 'keep.md'), 'regular file should stay');
|
|
197
|
+
const vectorDatabase = createVectorDatabase();
|
|
198
|
+
const context = new context_1.Context({
|
|
199
|
+
embedding: new TestEmbedding(),
|
|
200
|
+
vectorDatabase,
|
|
201
|
+
codeSplitter: new TestSplitter(),
|
|
202
|
+
});
|
|
203
|
+
await context.indexCodebase(project);
|
|
204
|
+
const insertedDocuments = vectorDatabase.insert.mock.calls
|
|
205
|
+
.flatMap(([, documents]) => documents);
|
|
206
|
+
const indexedPaths = insertedDocuments
|
|
207
|
+
.map(document => document.relativePath.replace(/\\/g, '/'))
|
|
208
|
+
.sort();
|
|
209
|
+
expect(indexedPaths).toEqual([
|
|
210
|
+
'src/Library/nested.md',
|
|
211
|
+
'src/keep.md',
|
|
212
|
+
]);
|
|
213
|
+
});
|
|
214
|
+
it('treats leading-slash directory ignore patterns as root-anchored and recursive during sync', async () => {
|
|
215
|
+
const project = path.join(tempRoot, 'project');
|
|
216
|
+
await fs.mkdir(path.join(project, 'Library'), { recursive: true });
|
|
217
|
+
await fs.mkdir(path.join(project, 'src', 'Library'), { recursive: true });
|
|
218
|
+
await fs.writeFile(path.join(project, 'Library', 'generated.md'), 'root library should be ignored');
|
|
219
|
+
await fs.writeFile(path.join(project, 'src', 'Library', 'nested.md'), 'nested library should stay');
|
|
220
|
+
await fs.writeFile(path.join(project, 'src', 'keep.md'), 'regular file should stay');
|
|
221
|
+
const synchronizer = new synchronizer_1.FileSynchronizer(project, ['/Library/'], ['.md']);
|
|
222
|
+
const fileHashes = await synchronizer.generateFileHashes(project);
|
|
223
|
+
expect(fileHashes.has(path.join('Library', 'generated.md'))).toBe(false);
|
|
224
|
+
expect(fileHashes.has(path.join('src', 'Library', 'nested.md'))).toBe(true);
|
|
225
|
+
expect(fileHashes.has(path.join('src', 'keep.md'))).toBe(true);
|
|
226
|
+
});
|
|
96
227
|
});
|
|
97
228
|
//# sourceMappingURL=context.ignore-patterns.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.ignore-patterns.test.js","sourceRoot":"","sources":["../src/context.ignore-patterns.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAkC;AAClC,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAoC;
|
|
1
|
+
{"version":3,"file":"context.ignore-patterns.test.js","sourceRoot":"","sources":["../src/context.ignore-patterns.test.ts"],"names":[],"mappings":"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"}
|
package/dist/context.js
CHANGED
|
@@ -45,7 +45,7 @@ const DEFAULT_SUPPORTED_EXTENSIONS = [
|
|
|
45
45
|
// Programming languages
|
|
46
46
|
'.ts', '.tsx', '.js', '.jsx', '.py', '.java', '.cpp', '.c', '.h', '.hpp',
|
|
47
47
|
'.cs', '.go', '.rs', '.php', '.rb', '.swift', '.kt', '.scala', '.m', '.mm',
|
|
48
|
-
'.dart',
|
|
48
|
+
'.dart', '.sol',
|
|
49
49
|
// Text and markup files
|
|
50
50
|
'.md', '.markdown', '.ipynb',
|
|
51
51
|
// '.txt', '.json', '.yaml', '.yml', '.xml', '.html', '.htm',
|
|
@@ -167,6 +167,14 @@ class Context {
|
|
|
167
167
|
getSupportedExtensions() {
|
|
168
168
|
return [...this.supportedExtensions];
|
|
169
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Get supported extensions for the current operation without mutating
|
|
172
|
+
* the Context's persistent extension list.
|
|
173
|
+
*/
|
|
174
|
+
getEffectiveSupportedExtensions(additionalExtensions = []) {
|
|
175
|
+
const normalizedExtensions = this.normalizeExtensions(additionalExtensions);
|
|
176
|
+
return [...new Set([...this.supportedExtensions, ...normalizedExtensions])];
|
|
177
|
+
}
|
|
170
178
|
/**
|
|
171
179
|
* Get ignore patterns
|
|
172
180
|
*/
|
|
@@ -268,12 +276,16 @@ class Context {
|
|
|
268
276
|
* @param codebasePath Codebase root path
|
|
269
277
|
* @param progressCallback Optional progress callback function
|
|
270
278
|
* @param forceReindex Whether to recreate the collection even if it exists
|
|
279
|
+
* @param additionalIgnorePatterns Request-scoped ignore patterns
|
|
280
|
+
* @param additionalSupportedExtensions Request-scoped file extensions
|
|
281
|
+
* @param requestSplitter Request-scoped splitter for this indexing run
|
|
271
282
|
* @returns Indexing statistics
|
|
272
283
|
*/
|
|
273
|
-
async indexCodebase(codebasePath, progressCallback, forceReindex = false, additionalIgnorePatterns = []) {
|
|
284
|
+
async indexCodebase(codebasePath, progressCallback, forceReindex = false, additionalIgnorePatterns = [], additionalSupportedExtensions = [], requestSplitter) {
|
|
274
285
|
const isHybrid = this.getIsHybrid();
|
|
275
286
|
const searchType = isHybrid === true ? 'hybrid search' : 'semantic search';
|
|
276
287
|
console.log(`[Context] 🚀 Starting to index codebase with ${searchType}: ${codebasePath}`);
|
|
288
|
+
const splitter = requestSplitter || this.codeSplitter;
|
|
277
289
|
// 1. Compute ignore patterns for this codebase/request without
|
|
278
290
|
// retaining file-based patterns from previous codebases.
|
|
279
291
|
const ignorePatterns = await this.loadIgnorePatterns(codebasePath, additionalIgnorePatterns);
|
|
@@ -283,7 +295,8 @@ class Context {
|
|
|
283
295
|
await this.prepareCollection(codebasePath, forceReindex);
|
|
284
296
|
// 3. Recursively traverse codebase to get all supported files
|
|
285
297
|
progressCallback?.({ phase: 'Scanning files...', current: 5, total: 100, percentage: 5 });
|
|
286
|
-
const
|
|
298
|
+
const supportedExtensions = this.getEffectiveSupportedExtensions(additionalSupportedExtensions);
|
|
299
|
+
const codeFiles = await this.getCodeFiles(codebasePath, ignorePatterns, supportedExtensions);
|
|
287
300
|
console.log(`[Context] 📁 Found ${codeFiles.length} code files`);
|
|
288
301
|
if (codeFiles.length === 0) {
|
|
289
302
|
progressCallback?.({ phase: 'No files to index', current: 100, total: 100, percentage: 100 });
|
|
@@ -304,7 +317,7 @@ class Context {
|
|
|
304
317
|
total: totalFiles,
|
|
305
318
|
percentage: Math.round(progressPercentage)
|
|
306
319
|
});
|
|
307
|
-
});
|
|
320
|
+
}, splitter);
|
|
308
321
|
console.log(`[Context] ✅ Codebase indexing completed! Processed ${result.processedFiles} files in total, generated ${result.totalChunks} code chunks`);
|
|
309
322
|
progressCallback?.({
|
|
310
323
|
phase: 'Indexing complete!',
|
|
@@ -318,14 +331,17 @@ class Context {
|
|
|
318
331
|
status: result.status
|
|
319
332
|
};
|
|
320
333
|
}
|
|
321
|
-
async reindexByChange(codebasePath, progressCallback) {
|
|
334
|
+
async reindexByChange(codebasePath, progressCallback, additionalIgnorePatterns = [], additionalSupportedExtensions = [], requestSplitter) {
|
|
322
335
|
const collectionName = this.getCollectionName(codebasePath);
|
|
323
336
|
const synchronizer = this.synchronizers.get(collectionName);
|
|
337
|
+
const splitter = requestSplitter || this.codeSplitter;
|
|
324
338
|
if (!synchronizer) {
|
|
325
|
-
//
|
|
326
|
-
|
|
339
|
+
// Recreate the synchronizer with the same request-scoped options that
|
|
340
|
+
// were used for the original indexing task.
|
|
341
|
+
const ignorePatterns = await this.loadIgnorePatterns(codebasePath, additionalIgnorePatterns);
|
|
342
|
+
const supportedExtensions = this.getEffectiveSupportedExtensions(additionalSupportedExtensions);
|
|
327
343
|
// To be safe, let's initialize if it's not there.
|
|
328
|
-
const newSynchronizer = new synchronizer_1.FileSynchronizer(codebasePath, ignorePatterns,
|
|
344
|
+
const newSynchronizer = new synchronizer_1.FileSynchronizer(codebasePath, ignorePatterns, supportedExtensions);
|
|
329
345
|
await newSynchronizer.initialize();
|
|
330
346
|
this.synchronizers.set(collectionName, newSynchronizer);
|
|
331
347
|
}
|
|
@@ -360,7 +376,7 @@ class Context {
|
|
|
360
376
|
if (filesToIndex.length > 0) {
|
|
361
377
|
await this.processFileList(filesToIndex, codebasePath, (filePath, fileIndex, totalFiles) => {
|
|
362
378
|
updateProgress(`Indexed ${filePath} (${fileIndex}/${totalFiles})`);
|
|
363
|
-
});
|
|
379
|
+
}, splitter);
|
|
364
380
|
}
|
|
365
381
|
console.log(`[Context] ✅ Re-indexing complete. Added: ${added.length}, Removed: ${removed.length}, Modified: ${modified.length}`);
|
|
366
382
|
progressCallback?.({ phase: 'Re-indexing complete!', current: totalChanges, total: totalChanges, percentage: 100 });
|
|
@@ -448,11 +464,12 @@ class Context {
|
|
|
448
464
|
language: result.document.metadata.language || 'unknown',
|
|
449
465
|
score: result.score
|
|
450
466
|
}));
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
467
|
+
const dedupedResults = this.deduplicateResults(results);
|
|
468
|
+
console.log(`[Context] ✅ Found ${results.length} results, ${dedupedResults.length} after dedup`);
|
|
469
|
+
if (dedupedResults.length > 0) {
|
|
470
|
+
console.log(`[Context] 🔍 Top result score: ${dedupedResults[0].score}, path: ${dedupedResults[0].relativePath}`);
|
|
454
471
|
}
|
|
455
|
-
return
|
|
472
|
+
return dedupedResults;
|
|
456
473
|
}
|
|
457
474
|
else {
|
|
458
475
|
// Regular semantic search
|
|
@@ -469,9 +486,35 @@ class Context {
|
|
|
469
486
|
language: result.document.metadata.language || 'unknown',
|
|
470
487
|
score: result.score
|
|
471
488
|
}));
|
|
472
|
-
|
|
473
|
-
|
|
489
|
+
const dedupedResults = this.deduplicateResults(results);
|
|
490
|
+
console.log(`[Context] ✅ Found ${results.length} results, ${dedupedResults.length} after dedup`);
|
|
491
|
+
return dedupedResults;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Deduplicate search results by file + line range overlap.
|
|
496
|
+
* Keeps higher-scored result when two results from the same file overlap >50%.
|
|
497
|
+
*/
|
|
498
|
+
deduplicateResults(results) {
|
|
499
|
+
const kept = [];
|
|
500
|
+
for (const result of results) {
|
|
501
|
+
const overlaps = kept.some((existing) => {
|
|
502
|
+
if (existing.relativePath !== result.relativePath)
|
|
503
|
+
return false;
|
|
504
|
+
const overlapStart = Math.max(existing.startLine, result.startLine);
|
|
505
|
+
const overlapEnd = Math.min(existing.endLine, result.endLine);
|
|
506
|
+
if (overlapStart > overlapEnd)
|
|
507
|
+
return false;
|
|
508
|
+
// Line ranges are inclusive (endLine = startLine + N - 1).
|
|
509
|
+
const overlapSize = overlapEnd - overlapStart + 1;
|
|
510
|
+
const resultSize = result.endLine - result.startLine + 1;
|
|
511
|
+
return resultSize > 0 && overlapSize / resultSize > 0.5;
|
|
512
|
+
});
|
|
513
|
+
if (!overlaps) {
|
|
514
|
+
kept.push(result);
|
|
515
|
+
}
|
|
474
516
|
}
|
|
517
|
+
return kept;
|
|
475
518
|
}
|
|
476
519
|
/**
|
|
477
520
|
* Check if index exists for codebase
|
|
@@ -591,7 +634,7 @@ class Context {
|
|
|
591
634
|
/**
|
|
592
635
|
* Recursively get all code files in the codebase
|
|
593
636
|
*/
|
|
594
|
-
async getCodeFiles(codebasePath, ignorePatterns = this.ignorePatterns) {
|
|
637
|
+
async getCodeFiles(codebasePath, ignorePatterns = this.ignorePatterns, supportedExtensions = this.supportedExtensions) {
|
|
595
638
|
const files = [];
|
|
596
639
|
const traverseDirectory = async (currentPath) => {
|
|
597
640
|
const entries = await fs.promises.readdir(currentPath, { withFileTypes: true });
|
|
@@ -606,7 +649,7 @@ class Context {
|
|
|
606
649
|
}
|
|
607
650
|
else if (entry.isFile()) {
|
|
608
651
|
const ext = path.extname(entry.name);
|
|
609
|
-
if (
|
|
652
|
+
if (supportedExtensions.includes(ext)) {
|
|
610
653
|
files.push(fullPath);
|
|
611
654
|
}
|
|
612
655
|
}
|
|
@@ -622,7 +665,7 @@ class Context {
|
|
|
622
665
|
* @param onFileProcessed Callback called when each file is processed
|
|
623
666
|
* @returns Object with processed file count and total chunk count
|
|
624
667
|
*/
|
|
625
|
-
async processFileList(filePaths, codebasePath, onFileProcessed) {
|
|
668
|
+
async processFileList(filePaths, codebasePath, onFileProcessed, splitter = this.codeSplitter) {
|
|
626
669
|
const isHybrid = this.getIsHybrid();
|
|
627
670
|
const EMBEDDING_BATCH_SIZE = Math.max(1, parseInt(env_manager_1.envManager.get('EMBEDDING_BATCH_SIZE') || '100', 10));
|
|
628
671
|
const CHUNK_LIMIT = 450000;
|
|
@@ -636,7 +679,7 @@ class Context {
|
|
|
636
679
|
try {
|
|
637
680
|
const content = await fs.promises.readFile(filePath, 'utf-8');
|
|
638
681
|
const language = this.getLanguageFromExtension(path.extname(filePath));
|
|
639
|
-
const chunks = await
|
|
682
|
+
const chunks = await splitter.split(content, language, filePath);
|
|
640
683
|
// Log files with many chunks or large content
|
|
641
684
|
if (chunks.length > 50) {
|
|
642
685
|
console.warn(`[Context] ⚠️ File ${filePath} generated ${chunks.length} chunks (${Math.round(content.length / 1024)}KB)`);
|
|
@@ -808,6 +851,7 @@ class Context {
|
|
|
808
851
|
'.m': 'objective-c',
|
|
809
852
|
'.mm': 'objective-c',
|
|
810
853
|
'.dart': 'dart',
|
|
854
|
+
'.sol': 'solidity',
|
|
811
855
|
'.ipynb': 'jupyter'
|
|
812
856
|
};
|
|
813
857
|
return languageMap[ext] || 'text';
|
|
@@ -992,22 +1036,46 @@ class Context {
|
|
|
992
1036
|
* @returns True if pattern matches
|
|
993
1037
|
*/
|
|
994
1038
|
isPatternMatch(filePath, pattern) {
|
|
1039
|
+
const cleanPath = filePath.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '');
|
|
1040
|
+
const normalizedPattern = pattern.replace(/\\/g, '/');
|
|
1041
|
+
const cleanPattern = normalizedPattern.replace(/^\/+|\/+$/g, '');
|
|
1042
|
+
const isRootAnchored = normalizedPattern.startsWith('/');
|
|
1043
|
+
const isDirectoryPattern = normalizedPattern.endsWith('/');
|
|
1044
|
+
if (!cleanPath || !cleanPattern) {
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
995
1047
|
// Handle directory patterns (ending with /)
|
|
996
|
-
if (
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1048
|
+
if (isDirectoryPattern) {
|
|
1049
|
+
if (isRootAnchored) {
|
|
1050
|
+
return this.simpleGlobMatch(cleanPath, cleanPattern) ||
|
|
1051
|
+
cleanPath.startsWith(`${cleanPattern}/`);
|
|
1052
|
+
}
|
|
1053
|
+
return this.matchesDirectoryPattern(cleanPath, cleanPattern);
|
|
1054
|
+
}
|
|
1055
|
+
if (isRootAnchored) {
|
|
1056
|
+
return this.simpleGlobMatch(cleanPath, cleanPattern);
|
|
1000
1057
|
}
|
|
1001
1058
|
// Handle file patterns
|
|
1002
|
-
if (
|
|
1059
|
+
if (cleanPattern.includes('/')) {
|
|
1003
1060
|
// Pattern with path separator - match exact path
|
|
1004
|
-
return this.simpleGlobMatch(
|
|
1061
|
+
return this.simpleGlobMatch(cleanPath, cleanPattern);
|
|
1005
1062
|
}
|
|
1006
1063
|
else {
|
|
1007
1064
|
// Pattern without path separator - match filename in any directory
|
|
1008
|
-
const fileName = path.basename(
|
|
1009
|
-
return this.simpleGlobMatch(fileName,
|
|
1065
|
+
const fileName = path.basename(cleanPath);
|
|
1066
|
+
return this.simpleGlobMatch(fileName, cleanPattern);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
matchesDirectoryPattern(filePath, dirPattern) {
|
|
1070
|
+
const pathParts = filePath.split('/');
|
|
1071
|
+
const dirPartCount = dirPattern.split('/').length;
|
|
1072
|
+
for (let i = 0; i <= pathParts.length - dirPartCount; i++) {
|
|
1073
|
+
const candidate = pathParts.slice(i, i + dirPartCount).join('/');
|
|
1074
|
+
if (this.simpleGlobMatch(candidate, dirPattern)) {
|
|
1075
|
+
return true;
|
|
1076
|
+
}
|
|
1010
1077
|
}
|
|
1078
|
+
return false;
|
|
1011
1079
|
}
|
|
1012
1080
|
/**
|
|
1013
1081
|
* Simple glob matching supporting * wildcard
|
|
@@ -1071,6 +1139,12 @@ class Context {
|
|
|
1071
1139
|
return [];
|
|
1072
1140
|
}
|
|
1073
1141
|
}
|
|
1142
|
+
normalizeExtensions(extensions) {
|
|
1143
|
+
return extensions
|
|
1144
|
+
.map(ext => ext.trim())
|
|
1145
|
+
.filter(ext => ext.length > 0)
|
|
1146
|
+
.map(ext => ext.startsWith('.') ? ext : `.${ext}`);
|
|
1147
|
+
}
|
|
1074
1148
|
/**
|
|
1075
1149
|
* Add custom extensions (from MCP or other sources) without replacing existing ones
|
|
1076
1150
|
* @param customExtensions Array of custom extensions to add
|
|
@@ -1078,8 +1152,7 @@ class Context {
|
|
|
1078
1152
|
addCustomExtensions(customExtensions) {
|
|
1079
1153
|
if (customExtensions.length === 0)
|
|
1080
1154
|
return;
|
|
1081
|
-
|
|
1082
|
-
const normalizedExtensions = customExtensions.map(ext => ext.startsWith('.') ? ext : `.${ext}`);
|
|
1155
|
+
const normalizedExtensions = this.normalizeExtensions(customExtensions);
|
|
1083
1156
|
// Merge current extensions with new custom extensions, avoiding duplicates
|
|
1084
1157
|
const mergedExtensions = [...this.supportedExtensions, ...normalizedExtensions];
|
|
1085
1158
|
const uniqueExtensions = [...new Set(mergedExtensions)];
|