@customize-agent/knowledge 4.0.1 → 4.0.2
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/dist/chunking/bge-tokenizer.d.ts +10 -0
- package/dist/chunking/bge-tokenizer.js +68 -0
- package/dist/chunking/text-chunker.d.ts +10 -0
- package/dist/chunking/text-chunker.js +158 -53
- package/dist/classification/classifier.js +0 -1
- package/dist/core/index-state-store.d.ts +47 -0
- package/dist/core/index-state-store.js +184 -50
- package/dist/core/knowledge-base-manager.d.ts +24 -2
- package/dist/core/knowledge-base-manager.js +195 -51
- package/dist/core/multi-project-manager.d.ts +2 -0
- package/dist/core/multi-project-manager.js +13 -2
- package/dist/embedding/embedding-provider.d.ts +22 -0
- package/dist/embedding/embedding-provider.js +116 -2
- package/dist/extraction/content-extractor.d.ts +30 -2
- package/dist/extraction/content-extractor.js +514 -115
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/search/federation-search.d.ts +1 -0
- package/dist/search/federation-search.js +1 -0
- package/dist/vector/hnsw-vector-store.d.ts +20 -0
- package/dist/vector/hnsw-vector-store.js +107 -0
- package/dist/vector/types.d.ts +2 -0
- package/dist/vector/vector-indexer.d.ts +2 -0
- package/dist/vector/vector-indexer.js +13 -1
- package/models/bge-small-zh-v1.5/config.json +31 -0
- package/models/bge-small-zh-v1.5/onnx/model_quantized.onnx +0 -0
- package/models/bge-small-zh-v1.5/special_tokens_map.json +7 -0
- package/models/bge-small-zh-v1.5/tokenizer.json +21278 -0
- package/models/bge-small-zh-v1.5/tokenizer_config.json +15 -0
- package/package.json +11 -4
- package/scripts/install-hnsw.cjs +47 -0
- package/dist/vector/sqlite-vec-store.d.ts +0 -38
- package/dist/vector/sqlite-vec-store.js +0 -203
|
@@ -56,11 +56,64 @@ export class IndexStateStore {
|
|
|
56
56
|
`).all();
|
|
57
57
|
return rows.map(row => this.rowToRecord(row));
|
|
58
58
|
}
|
|
59
|
+
enqueueIndexJob(job) {
|
|
60
|
+
const now = Date.now();
|
|
61
|
+
this.db.prepare(`
|
|
62
|
+
INSERT INTO kb_index_jobs (id, relative_path, status, percent, message, created_at, updated_at)
|
|
63
|
+
VALUES (?, ?, 'PENDING', 0, ?, ?, ?)
|
|
64
|
+
ON CONFLICT(id) DO UPDATE SET status = 'PENDING', percent = 0, message = excluded.message, error_message = NULL, updated_at = excluded.updated_at
|
|
65
|
+
`).run(job.id, job.relativePath, job.message ?? '等待后台索引', now, now);
|
|
66
|
+
return this.getIndexJob(job.id);
|
|
67
|
+
}
|
|
68
|
+
updateIndexJob(id, patch) {
|
|
69
|
+
const current = this.getIndexJob(id);
|
|
70
|
+
if (!current)
|
|
71
|
+
return;
|
|
72
|
+
this.db.prepare(`
|
|
73
|
+
UPDATE kb_index_jobs
|
|
74
|
+
SET status = ?, percent = ?, message = ?, error_message = ?, updated_at = ?
|
|
75
|
+
WHERE id = ?
|
|
76
|
+
`).run(patch.status ?? current.status, patch.percent ?? current.percent, patch.message ?? current.message, patch.errorMessage ?? null, Date.now(), id);
|
|
77
|
+
}
|
|
78
|
+
getIndexJob(id) {
|
|
79
|
+
const row = this.db.prepare('SELECT * FROM kb_index_jobs WHERE id = ?').get(id);
|
|
80
|
+
return row ? this.rowToJob(row) : undefined;
|
|
81
|
+
}
|
|
82
|
+
listPendingIndexJobs(limit = 20) {
|
|
83
|
+
const rows = this.db.prepare(`
|
|
84
|
+
SELECT * FROM kb_index_jobs
|
|
85
|
+
WHERE status = 'PENDING'
|
|
86
|
+
ORDER BY created_at ASC
|
|
87
|
+
LIMIT ?
|
|
88
|
+
`).all(limit);
|
|
89
|
+
return rows.map(row => this.rowToJob(row));
|
|
90
|
+
}
|
|
91
|
+
countPendingIndexJobs() {
|
|
92
|
+
const row = this.db.prepare("SELECT COUNT(*) as count FROM kb_index_jobs WHERE status = 'PENDING'").get();
|
|
93
|
+
return Number(row?.count ?? 0);
|
|
94
|
+
}
|
|
95
|
+
listActiveIndexJobsByPath(relativePath) {
|
|
96
|
+
const rows = this.db.prepare(`
|
|
97
|
+
SELECT * FROM kb_index_jobs
|
|
98
|
+
WHERE relative_path = ? AND status IN ('PENDING', 'PARSING', 'CHUNKING', 'INDEXING')
|
|
99
|
+
ORDER BY created_at ASC
|
|
100
|
+
`).all(relativePath);
|
|
101
|
+
return rows.map(row => this.rowToJob(row));
|
|
102
|
+
}
|
|
103
|
+
listIndexJobsByPrefix(prefix) {
|
|
104
|
+
const rows = this.db.prepare(`
|
|
105
|
+
SELECT * FROM kb_index_jobs
|
|
106
|
+
WHERE id LIKE ?
|
|
107
|
+
ORDER BY created_at ASC
|
|
108
|
+
`).all(`${prefix}%`);
|
|
109
|
+
return rows.map(row => this.rowToJob(row));
|
|
110
|
+
}
|
|
59
111
|
replaceChunks(relativePath, chunks, file) {
|
|
60
112
|
const now = Date.now();
|
|
61
113
|
const transaction = this.db.transaction(() => {
|
|
62
114
|
this.db.prepare('DELETE FROM kb_chunks WHERE relative_path = ?').run(relativePath);
|
|
63
115
|
this.db.prepare('DELETE FROM kb_parent_chunks WHERE relative_path = ?').run(relativePath);
|
|
116
|
+
this.db.prepare('DELETE FROM kb_document_chunks WHERE relative_path = ?').run(relativePath);
|
|
64
117
|
if (this.ftsEnabled)
|
|
65
118
|
this.db.prepare('DELETE FROM kb_chunks_fts WHERE relative_path = ?').run(relativePath);
|
|
66
119
|
const insert = this.db.prepare(`
|
|
@@ -78,6 +131,12 @@ export class IndexStateStore {
|
|
|
78
131
|
id, relative_path, parent_id, content, category, format,
|
|
79
132
|
collection_name, section_title, chunk_count, metadata_json, created_at
|
|
80
133
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
134
|
+
`);
|
|
135
|
+
const insertDocument = this.db.prepare(`
|
|
136
|
+
INSERT INTO kb_document_chunks (
|
|
137
|
+
id, relative_path, content, category, format,
|
|
138
|
+
collection_name, parent_count, chunk_count, metadata_json, created_at
|
|
139
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
81
140
|
`);
|
|
82
141
|
const parentGroups = new Map();
|
|
83
142
|
const groupedChunks = this.splitParentGroups(relativePath, chunks);
|
|
@@ -87,9 +146,13 @@ export class IndexStateStore {
|
|
|
87
146
|
group.push(chunk);
|
|
88
147
|
parentGroups.set(parentId, group);
|
|
89
148
|
}
|
|
149
|
+
const parentContents = [];
|
|
90
150
|
for (const [parentId, group] of parentGroups.entries()) {
|
|
91
|
-
|
|
151
|
+
const parentContent = group.map(chunk => chunk.text).join('\n\n---\n\n');
|
|
152
|
+
parentContents.push(parentContent);
|
|
153
|
+
insertParent.run(parentId, relativePath, parentId, parentContent, file.category, file.format, file.collectionName, group.find(chunk => chunk.sectionTitle)?.sectionTitle ?? null, group.length, JSON.stringify({ parentId, splitStrategy: this.metadataString(group[0]?.metadata.splitStrategy), chunkKind: this.metadataString(group[0]?.metadata.chunkKind) }), now);
|
|
92
154
|
}
|
|
155
|
+
insertDocument.run(`${relativePath}#document`, relativePath, parentContents.join('\n\n=== SECTION ===\n\n'), file.category, file.format, file.collectionName, parentGroups.size, groupedChunks.length, JSON.stringify({ parentType: 'document', splitStrategy: 'document_section_child_v1' }), now);
|
|
93
156
|
for (const chunk of groupedChunks) {
|
|
94
157
|
const chunkId = `${relativePath}#${chunk.index}`;
|
|
95
158
|
insert.run(chunkId, relativePath, chunk.index, chunk.text, file.category, file.format, file.collectionName, chunk.tokenCount, chunk.sectionTitle ?? null, JSON.stringify(chunk.metadata), now);
|
|
@@ -114,16 +177,28 @@ export class IndexStateStore {
|
|
|
114
177
|
if (options.limit)
|
|
115
178
|
params.push(options.limit);
|
|
116
179
|
const rows = this.db.prepare(`
|
|
117
|
-
SELECT * FROM kb_chunks
|
|
180
|
+
SELECT rowid, * FROM kb_chunks
|
|
118
181
|
${where}
|
|
119
182
|
ORDER BY relative_path, chunk_index
|
|
120
183
|
${limit}
|
|
121
184
|
`).all(...params);
|
|
122
185
|
return rows.map(row => this.rowToChunk(row, 0));
|
|
123
186
|
}
|
|
187
|
+
getChunkByRowid(rowid) {
|
|
188
|
+
const row = this.db.prepare('SELECT rowid, * FROM kb_chunks WHERE rowid = ?').get(rowid);
|
|
189
|
+
return row ? this.rowToChunk(row, 0) : undefined;
|
|
190
|
+
}
|
|
191
|
+
getChunksByRowids(rowids) {
|
|
192
|
+
if (rowids.length === 0)
|
|
193
|
+
return [];
|
|
194
|
+
const placeholders = rowids.map(() => '?').join(',');
|
|
195
|
+
const rows = this.db.prepare(`SELECT rowid, * FROM kb_chunks WHERE rowid IN (${placeholders})`).all(...rowids);
|
|
196
|
+
const byRowid = new Map(rows.map(row => [Number(row.rowid), this.rowToChunk(row, 0)]));
|
|
197
|
+
return rowids.flatMap(rowid => byRowid.get(rowid) ?? []);
|
|
198
|
+
}
|
|
124
199
|
getContextChunks(relativePath, chunkIndex, window = 1) {
|
|
125
200
|
const rows = this.db.prepare(`
|
|
126
|
-
SELECT * FROM kb_chunks
|
|
201
|
+
SELECT rowid, * FROM kb_chunks
|
|
127
202
|
WHERE relative_path = ? AND chunk_index BETWEEN ? AND ?
|
|
128
203
|
ORDER BY chunk_index
|
|
129
204
|
`).all(relativePath, Math.max(0, chunkIndex - window), chunkIndex + window);
|
|
@@ -145,9 +220,17 @@ export class IndexStateStore {
|
|
|
145
220
|
`).get(relativePath, parentId);
|
|
146
221
|
return row ? this.rowToParentChunk(row) : undefined;
|
|
147
222
|
}
|
|
223
|
+
getDocumentChunk(relativePath) {
|
|
224
|
+
const row = this.db.prepare(`
|
|
225
|
+
SELECT * FROM kb_document_chunks
|
|
226
|
+
WHERE relative_path = ?
|
|
227
|
+
LIMIT 1
|
|
228
|
+
`).get(relativePath);
|
|
229
|
+
return row ? this.rowToDocumentChunk(row) : undefined;
|
|
230
|
+
}
|
|
148
231
|
getChunksByParent(relativePath, parentId, limit = 6) {
|
|
149
232
|
const rows = this.db.prepare(`
|
|
150
|
-
SELECT * FROM kb_chunks
|
|
233
|
+
SELECT rowid, * FROM kb_chunks
|
|
151
234
|
WHERE relative_path = ? AND metadata_json LIKE ?
|
|
152
235
|
ORDER BY chunk_index
|
|
153
236
|
LIMIT ?
|
|
@@ -158,12 +241,11 @@ export class IndexStateStore {
|
|
|
158
241
|
const terms = this.expandSearchTerms(query);
|
|
159
242
|
if (terms.length === 0)
|
|
160
243
|
return [];
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return this.searchChunksLike(terms, limit);
|
|
244
|
+
const results = [
|
|
245
|
+
...(this.ftsEnabled ? this.searchChunksFts(terms, limit) : []),
|
|
246
|
+
...this.searchChunksLike(terms, limit),
|
|
247
|
+
];
|
|
248
|
+
return this.mergeKeywordResults(results, limit);
|
|
167
249
|
}
|
|
168
250
|
searchChunksFts(terms, limit) {
|
|
169
251
|
try {
|
|
@@ -171,7 +253,7 @@ export class IndexStateStore {
|
|
|
171
253
|
if (!matchQuery)
|
|
172
254
|
return [];
|
|
173
255
|
const rows = this.db.prepare(`
|
|
174
|
-
SELECT c.*, bm25(kb_chunks_fts, 1.2, 0.8, 0.6, 1.0, 2.0) as bm25_score
|
|
256
|
+
SELECT c.rowid, c.*, bm25(kb_chunks_fts, 1.2, 0.8, 0.6, 1.0, 2.0) as bm25_score
|
|
175
257
|
FROM kb_chunks_fts
|
|
176
258
|
INNER JOIN kb_chunks c ON c.id = kb_chunks_fts.id
|
|
177
259
|
WHERE kb_chunks_fts MATCH ?
|
|
@@ -194,7 +276,7 @@ export class IndexStateStore {
|
|
|
194
276
|
}
|
|
195
277
|
searchChunksLike(terms, limit) {
|
|
196
278
|
const rows = this.db.prepare(`
|
|
197
|
-
SELECT * FROM kb_chunks
|
|
279
|
+
SELECT rowid, * FROM kb_chunks
|
|
198
280
|
WHERE ${terms.map(() => '(LOWER(content) LIKE ? OR LOWER(relative_path) LIKE ? OR LOWER(category) LIKE ? OR LOWER(format) LIKE ?)').join(' OR ')}
|
|
199
281
|
ORDER BY created_at DESC
|
|
200
282
|
LIMIT ?
|
|
@@ -331,6 +413,7 @@ export class IndexStateStore {
|
|
|
331
413
|
deleteRecord(relativePath) {
|
|
332
414
|
this.db.prepare('DELETE FROM kb_chunks WHERE relative_path = ?').run(relativePath);
|
|
333
415
|
this.db.prepare('DELETE FROM kb_parent_chunks WHERE relative_path = ?').run(relativePath);
|
|
416
|
+
this.db.prepare('DELETE FROM kb_document_chunks WHERE relative_path = ?').run(relativePath);
|
|
334
417
|
if (this.ftsEnabled)
|
|
335
418
|
this.db.prepare('DELETE FROM kb_chunks_fts WHERE relative_path = ?').run(relativePath);
|
|
336
419
|
this.db.prepare('DELETE FROM kb_index_state WHERE relative_path = ?').run(relativePath);
|
|
@@ -398,7 +481,8 @@ export class IndexStateStore {
|
|
|
398
481
|
CREATE INDEX IF NOT EXISTS idx_kb_state_collection ON kb_index_state(collection_name);
|
|
399
482
|
|
|
400
483
|
CREATE TABLE IF NOT EXISTS kb_chunks (
|
|
401
|
-
|
|
484
|
+
rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
485
|
+
id TEXT NOT NULL UNIQUE,
|
|
402
486
|
relative_path TEXT NOT NULL,
|
|
403
487
|
chunk_index INTEGER NOT NULL,
|
|
404
488
|
content TEXT NOT NULL,
|
|
@@ -430,6 +514,20 @@ export class IndexStateStore {
|
|
|
430
514
|
CREATE INDEX IF NOT EXISTS idx_kb_parent_path ON kb_parent_chunks(relative_path);
|
|
431
515
|
CREATE INDEX IF NOT EXISTS idx_kb_parent_id ON kb_parent_chunks(parent_id);
|
|
432
516
|
|
|
517
|
+
CREATE TABLE IF NOT EXISTS kb_document_chunks (
|
|
518
|
+
id TEXT PRIMARY KEY,
|
|
519
|
+
relative_path TEXT NOT NULL,
|
|
520
|
+
content TEXT NOT NULL,
|
|
521
|
+
category TEXT NOT NULL,
|
|
522
|
+
format TEXT NOT NULL,
|
|
523
|
+
collection_name TEXT NOT NULL,
|
|
524
|
+
parent_count INTEGER NOT NULL,
|
|
525
|
+
chunk_count INTEGER NOT NULL,
|
|
526
|
+
metadata_json TEXT,
|
|
527
|
+
created_at INTEGER NOT NULL
|
|
528
|
+
);
|
|
529
|
+
CREATE INDEX IF NOT EXISTS idx_kb_document_path ON kb_document_chunks(relative_path);
|
|
530
|
+
|
|
433
531
|
CREATE TABLE IF NOT EXISTS kb_file_hashes (
|
|
434
532
|
content_hash TEXT NOT NULL,
|
|
435
533
|
file_path TEXT PRIMARY KEY,
|
|
@@ -481,6 +579,19 @@ export class IndexStateStore {
|
|
|
481
579
|
);
|
|
482
580
|
CREATE INDEX IF NOT EXISTS idx_tags_tag ON kb_tags(tag);
|
|
483
581
|
|
|
582
|
+
CREATE TABLE IF NOT EXISTS kb_index_jobs (
|
|
583
|
+
id TEXT PRIMARY KEY,
|
|
584
|
+
relative_path TEXT NOT NULL,
|
|
585
|
+
status TEXT NOT NULL,
|
|
586
|
+
percent INTEGER NOT NULL DEFAULT 0,
|
|
587
|
+
message TEXT NOT NULL DEFAULT '',
|
|
588
|
+
error_message TEXT,
|
|
589
|
+
created_at INTEGER NOT NULL,
|
|
590
|
+
updated_at INTEGER NOT NULL
|
|
591
|
+
);
|
|
592
|
+
CREATE INDEX IF NOT EXISTS idx_kb_jobs_status ON kb_index_jobs(status);
|
|
593
|
+
CREATE INDEX IF NOT EXISTS idx_kb_jobs_path ON kb_index_jobs(relative_path);
|
|
594
|
+
|
|
484
595
|
CREATE TABLE IF NOT EXISTS kb_metadata (
|
|
485
596
|
key TEXT PRIMARY KEY,
|
|
486
597
|
value TEXT NOT NULL
|
|
@@ -575,7 +686,7 @@ export class IndexStateStore {
|
|
|
575
686
|
relativePath: String(row.relative_path),
|
|
576
687
|
parentId: String(row.parent_id),
|
|
577
688
|
content: String(row.content),
|
|
578
|
-
category:
|
|
689
|
+
category: row.category,
|
|
579
690
|
format: String(row.format),
|
|
580
691
|
collectionName: String(row.collection_name),
|
|
581
692
|
sectionTitle: row.section_title == null ? undefined : String(row.section_title),
|
|
@@ -584,45 +695,41 @@ export class IndexStateStore {
|
|
|
584
695
|
createdAt: Number(row.created_at),
|
|
585
696
|
};
|
|
586
697
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
tokenCount += chunk.tokenCount;
|
|
616
|
-
}
|
|
617
|
-
flush();
|
|
618
|
-
}
|
|
619
|
-
return result.sort((a, b) => a.index - b.index);
|
|
698
|
+
rowToDocumentChunk(row) {
|
|
699
|
+
return {
|
|
700
|
+
id: String(row.id),
|
|
701
|
+
relativePath: String(row.relative_path),
|
|
702
|
+
content: String(row.content),
|
|
703
|
+
category: row.category,
|
|
704
|
+
format: String(row.format),
|
|
705
|
+
collectionName: String(row.collection_name),
|
|
706
|
+
parentCount: Number(row.parent_count),
|
|
707
|
+
chunkCount: Number(row.chunk_count),
|
|
708
|
+
metadataJson: row.metadata_json == null ? undefined : String(row.metadata_json),
|
|
709
|
+
createdAt: Number(row.created_at),
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
splitParentGroups(_relativePath, chunks) {
|
|
713
|
+
return chunks;
|
|
714
|
+
}
|
|
715
|
+
rowToJob(row) {
|
|
716
|
+
return {
|
|
717
|
+
id: String(row.id),
|
|
718
|
+
relativePath: String(row.relative_path),
|
|
719
|
+
status: String(row.status),
|
|
720
|
+
percent: Number(row.percent),
|
|
721
|
+
message: String(row.message ?? ''),
|
|
722
|
+
errorMessage: row.error_message == null ? undefined : String(row.error_message),
|
|
723
|
+
createdAt: Number(row.created_at),
|
|
724
|
+
updatedAt: Number(row.updated_at),
|
|
725
|
+
};
|
|
620
726
|
}
|
|
621
727
|
metadataString(value) {
|
|
622
728
|
return typeof value === 'string' ? value : undefined;
|
|
623
729
|
}
|
|
624
730
|
rowToChunk(row, score, scoreDetails) {
|
|
625
731
|
return {
|
|
732
|
+
rowid: Number(row.rowid ?? 0),
|
|
626
733
|
id: String(row.id),
|
|
627
734
|
relativePath: String(row.relative_path),
|
|
628
735
|
chunkIndex: Number(row.chunk_index),
|
|
@@ -641,8 +748,13 @@ export class IndexStateStore {
|
|
|
641
748
|
expandSearchTerms(query) {
|
|
642
749
|
const normalized = query.toLowerCase().trim();
|
|
643
750
|
const terms = new Set(normalized ? [normalized] : []);
|
|
644
|
-
for (const term of normalized.split(/[\s,,。;;::、]+/u).filter(Boolean))
|
|
751
|
+
for (const term of normalized.split(/[\s,,。;;::、]+/u).filter(Boolean)) {
|
|
645
752
|
terms.add(term);
|
|
753
|
+
for (const gram of this.chineseNgrams(term))
|
|
754
|
+
terms.add(gram);
|
|
755
|
+
}
|
|
756
|
+
for (const gram of this.chineseNgrams(normalized))
|
|
757
|
+
terms.add(gram);
|
|
646
758
|
const synonyms = {
|
|
647
759
|
招标: ['招标', '投标', '标书', '招标文件', '投标文件', 'bid', 'tender', 'bidding'],
|
|
648
760
|
投标: ['招标', '投标', '标书', '招标文件', '投标文件', 'bid', 'tender', 'bidding'],
|
|
@@ -656,7 +768,7 @@ export class IndexStateStore {
|
|
|
656
768
|
for (const value of values)
|
|
657
769
|
terms.add(value.toLowerCase());
|
|
658
770
|
}
|
|
659
|
-
return [...terms];
|
|
771
|
+
return [...terms].filter(term => term.length > 0).slice(0, 40);
|
|
660
772
|
}
|
|
661
773
|
toFtsQuery(terms) {
|
|
662
774
|
const normalized = terms.map(term => term.replace(/["*^:(){}\]\\[]/gu, ' ').trim()).filter(term => term.length > 0);
|
|
@@ -664,10 +776,32 @@ export class IndexStateStore {
|
|
|
664
776
|
const weak = normalized.slice(1).filter(term => term.length >= 2).slice(0, 12);
|
|
665
777
|
return [exact ? `"${exact}"` : '', ...weak.map(term => `"${term}"`)].filter(Boolean).join(' OR ');
|
|
666
778
|
}
|
|
779
|
+
mergeKeywordResults(results, limit) {
|
|
780
|
+
const byId = new Map();
|
|
781
|
+
for (const result of results) {
|
|
782
|
+
const existing = byId.get(result.id);
|
|
783
|
+
if (!existing || result.score > existing.score)
|
|
784
|
+
byId.set(result.id, result);
|
|
785
|
+
}
|
|
786
|
+
return [...byId.values()].sort((a, b) => b.score - a.score).slice(0, limit);
|
|
787
|
+
}
|
|
788
|
+
chineseNgrams(text) {
|
|
789
|
+
const han = text.match(/[\p{Script=Han}]+/gu) ?? [];
|
|
790
|
+
const grams = [];
|
|
791
|
+
for (const token of han) {
|
|
792
|
+
for (let size = 2; size <= 3; size++) {
|
|
793
|
+
if (token.length <= size)
|
|
794
|
+
continue;
|
|
795
|
+
for (let index = 0; index <= token.length - size; index++)
|
|
796
|
+
grams.push(token.slice(index, index + size));
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return grams;
|
|
800
|
+
}
|
|
667
801
|
bm25ToPositiveScore(score) {
|
|
668
802
|
if (!Number.isFinite(score))
|
|
669
803
|
return 0;
|
|
670
|
-
return 1 / (1 +
|
|
804
|
+
return score < 0 ? -score : 1 / (1 + score);
|
|
671
805
|
}
|
|
672
806
|
scoreChunkDetailed(content, terms) {
|
|
673
807
|
const lower = content.toLowerCase();
|
|
@@ -34,7 +34,7 @@ export declare class KnowledgeBaseManager {
|
|
|
34
34
|
readonly projectId?: string;
|
|
35
35
|
readonly kbPath: string;
|
|
36
36
|
readonly store: IndexStateStore;
|
|
37
|
-
private readonly
|
|
37
|
+
private readonly vectorRoot;
|
|
38
38
|
private readonly classifier;
|
|
39
39
|
private readonly scanner;
|
|
40
40
|
private readonly collections;
|
|
@@ -51,9 +51,19 @@ export declare class KnowledgeBaseManager {
|
|
|
51
51
|
private onProgress?;
|
|
52
52
|
constructor(options: KnowledgeBaseManagerOptions);
|
|
53
53
|
initialize(): void;
|
|
54
|
+
forceReindexAll(options?: {
|
|
55
|
+
onProgress?: (progress: KnowledgeIndexProgress) => void;
|
|
56
|
+
vectorMode?: 'sync' | 'defer';
|
|
57
|
+
}): Promise<DiffResult>;
|
|
58
|
+
consumePendingIndexJobs(options?: {
|
|
59
|
+
onProgress?: (progress: KnowledgeIndexProgress) => void;
|
|
60
|
+
vectorMode?: 'sync' | 'defer';
|
|
61
|
+
limit?: number;
|
|
62
|
+
}): Promise<DiffResult>;
|
|
54
63
|
incrementalIndex(options?: {
|
|
55
64
|
onProgress?: (progress: KnowledgeIndexProgress) => void;
|
|
56
65
|
vectorMode?: 'sync' | 'defer';
|
|
66
|
+
onlyRelativePaths?: string[];
|
|
57
67
|
}): Promise<DiffResult>;
|
|
58
68
|
search(query: string, limit?: number): ChunkSearchResult[];
|
|
59
69
|
keywordSearchItems(query: string, limit?: number): FederatedSearchItem[];
|
|
@@ -90,6 +100,11 @@ export declare class KnowledgeBaseManager {
|
|
|
90
100
|
uploadFile(fileName: string, content: Buffer, targetRelativePath?: string, onProgress?: (progress: KnowledgeIndexProgress) => void, options?: {
|
|
91
101
|
vectorMode?: 'sync' | 'defer';
|
|
92
102
|
}): Promise<DiffResult>;
|
|
103
|
+
stageUploadedFiles(files: Array<{
|
|
104
|
+
fileName: string;
|
|
105
|
+
content: Buffer;
|
|
106
|
+
targetRelativePath?: string;
|
|
107
|
+
}>, operationId?: string): Promise<import("./index-state-store.js").KnowledgeIndexJob[]>;
|
|
93
108
|
uploadFiles(files: Array<{
|
|
94
109
|
fileName: string;
|
|
95
110
|
content: Buffer;
|
|
@@ -119,6 +134,9 @@ export declare class KnowledgeBaseManager {
|
|
|
119
134
|
}): Promise<VectorIndexResult[]>;
|
|
120
135
|
getProjectConfig(): ProjectConfig | undefined;
|
|
121
136
|
getStats(): KnowledgeBaseStats;
|
|
137
|
+
listIndexJobsByPrefix(prefix: string): import("./index-state-store.js").KnowledgeIndexJob[];
|
|
138
|
+
countPendingIndexJobs(): number;
|
|
139
|
+
failPendingIndexJobs(message: string): void;
|
|
122
140
|
getVectorStatus(): {
|
|
123
141
|
status: string;
|
|
124
142
|
error?: string;
|
|
@@ -131,8 +149,11 @@ export declare class KnowledgeBaseManager {
|
|
|
131
149
|
private retrievalWeights;
|
|
132
150
|
private heuristicRerank;
|
|
133
151
|
private llmRerank;
|
|
152
|
+
private hydrateVectorResultsFromSqlite;
|
|
134
153
|
private toFederatedItem;
|
|
135
|
-
private
|
|
154
|
+
private mergeHybridRankedLists;
|
|
155
|
+
private mergeContexts;
|
|
156
|
+
private contextKey;
|
|
136
157
|
private parseChunkIndex;
|
|
137
158
|
private parseMetadataString;
|
|
138
159
|
private parseMetadata;
|
|
@@ -140,6 +161,7 @@ export declare class KnowledgeBaseManager {
|
|
|
140
161
|
private metadataFacets;
|
|
141
162
|
close(): void;
|
|
142
163
|
private reportProgress;
|
|
164
|
+
private updateJobsForFile;
|
|
143
165
|
private ensureVectorStore;
|
|
144
166
|
private deleteVectorFile;
|
|
145
167
|
private ensureVectorIndexFresh;
|