@remnic/core 9.3.563 → 9.3.565
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/access-cli.js +40 -39
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.js +16 -16
- package/dist/access-mcp.js +13 -13
- package/dist/access-schema.js +3 -3
- package/dist/access-service.js +11 -11
- package/dist/active-recall.js +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/briefing.js +4 -4
- package/dist/causal-consolidation.js +5 -5
- package/dist/{chunk-I2K6KCVC.js → chunk-2FHLI4U6.js} +49 -49
- package/dist/chunk-3ONXXHQO.js +57 -0
- package/dist/chunk-3ONXXHQO.js.map +1 -0
- package/dist/{chunk-5GX5MUQ2.js → chunk-574MU2Y3.js} +3 -3
- package/dist/{chunk-65OLPXBU.js → chunk-5WB4C7KM.js} +6 -6
- package/dist/chunk-6PTSXBPE.js +483 -0
- package/dist/chunk-6PTSXBPE.js.map +1 -0
- package/dist/{chunk-Z56KAZQL.js → chunk-74VA26CT.js} +2 -2
- package/dist/{chunk-CC2ESOOG.js → chunk-7X7TBJRX.js} +2 -2
- package/dist/{chunk-O4M4WH6V.js → chunk-ARY5OOLG.js} +2 -2
- package/dist/{chunk-JBPKEARU.js → chunk-AU7Q3LSC.js} +4 -4
- package/dist/{chunk-PM3QHTFT.js → chunk-CF3ZF2YU.js} +3 -3
- package/dist/{chunk-SI3QCHWF.js → chunk-DARLGSFX.js} +5 -5
- package/dist/chunk-EWLQPEO6.js +308 -0
- package/dist/chunk-EWLQPEO6.js.map +1 -0
- package/dist/{chunk-FVCZINOF.js → chunk-FHBEL473.js} +2 -2
- package/dist/{chunk-7Q3RCKAQ.js → chunk-FXKPZ3H6.js} +2 -2
- package/dist/{chunk-5WLYNZPC.js → chunk-GBXGCFRH.js} +2 -2
- package/dist/{chunk-ILJXM3FV.js → chunk-HQO5EBUC.js} +10 -10
- package/dist/{chunk-FK556DDH.js → chunk-I4UNL747.js} +4 -4
- package/dist/{chunk-RLPIT4YI.js → chunk-IOTTZLFF.js} +38 -38
- package/dist/{chunk-TVZ6LKKS.js → chunk-IRFF6LSF.js} +8 -8
- package/dist/{chunk-M5T4Q2ZU.js → chunk-KGK2QKWL.js} +1 -1
- package/dist/chunk-KGK2QKWL.js.map +1 -0
- package/dist/{chunk-IPLYGWQF.js → chunk-KQAFEZQX.js} +5 -5
- package/dist/chunk-M46RYSMW.js +597 -0
- package/dist/chunk-M46RYSMW.js.map +1 -0
- package/dist/{chunk-KXULCVOC.js → chunk-M6I5Z4SR.js} +4 -2
- package/dist/chunk-M6I5Z4SR.js.map +1 -0
- package/dist/{chunk-JFN6K74Q.js → chunk-MQEIWDYW.js} +2 -2
- package/dist/{chunk-7H6CFEBJ.js → chunk-NZPF2SYV.js} +8 -1
- package/dist/{chunk-7H6CFEBJ.js.map → chunk-NZPF2SYV.js.map} +1 -1
- package/dist/{chunk-SML26KED.js → chunk-OB6353F7.js} +16 -12
- package/dist/chunk-OB6353F7.js.map +1 -0
- package/dist/{chunk-SOTR74FK.js → chunk-OPYFD6PD.js} +2 -2
- package/dist/{chunk-3C5RPJAX.js → chunk-OXJBNGBK.js} +2 -2
- package/dist/{chunk-BD5LHQWD.js → chunk-PPPZY2EU.js} +2 -2
- package/dist/{chunk-25BY3HHZ.js → chunk-SUTSSOYU.js} +2 -2
- package/dist/{chunk-KS7WO6EQ.js → chunk-VFB2G5YL.js} +20 -20
- package/dist/{chunk-BUUYY2H2.js → chunk-WP5OWVLZ.js} +4 -4
- package/dist/{chunk-6URPAY2D.js → chunk-XCAZF7KQ.js} +207 -53
- package/dist/chunk-XCAZF7KQ.js.map +1 -0
- package/dist/{chunk-S53PAX2V.js → chunk-XM7BYXT7.js} +2 -2
- package/dist/{chunk-FADZBOR4.js → chunk-XRWTAEZM.js} +2 -2
- package/dist/{chunk-E5OECWZ5.js → chunk-XT7XVA53.js} +2 -2
- package/dist/{chunk-R3PS27B4.js → chunk-Z4R6RI2N.js} +2 -2
- package/dist/cli.js +44 -43
- package/dist/compounding/engine.js +4 -4
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.js +4 -4
- package/dist/connectors/index.js +4 -4
- package/dist/embedding-fallback.d.ts +12 -1
- package/dist/embedding-fallback.js +4 -1
- package/dist/entity-retrieval.js +4 -4
- package/dist/host-embedding-provider.d.ts +21 -0
- package/dist/host-embedding-provider.js +14 -0
- package/dist/host-embedding-provider.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +71 -63
- package/dist/index.js.map +1 -1
- package/dist/lcm/index.js +3 -3
- package/dist/maintenance/memory-governance.js +4 -4
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +4 -4
- package/dist/maintenance/rebuild-memory-projection.js +5 -5
- package/dist/namespaces/migrate.js +14 -13
- package/dist/namespaces/search.js +9 -8
- package/dist/namespaces/storage.js +4 -4
- package/dist/operator-toolkit.js +17 -16
- package/dist/orchestrator.js +32 -31
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.js +2 -2
- package/dist/resume-bundles.js +2 -2
- package/dist/search/embed-helper.d.ts +48 -4
- package/dist/search/embed-helper.js +2 -1
- package/dist/search/factory.js +8 -7
- package/dist/search/index.d.ts +1 -0
- package/dist/search/index.js +12 -11
- package/dist/search/lancedb-backend.d.ts +11 -0
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/orama-backend.d.ts +16 -0
- package/dist/search/orama-backend.js +2 -2
- package/dist/semantic-consolidation.js +5 -5
- package/dist/semantic-rule-promotion.js +4 -4
- package/dist/semantic-rule-verifier.js +4 -4
- package/dist/storage.js +3 -3
- package/dist/transfer/autodetect.js +1 -1
- package/dist/transfer/backup.js +1 -1
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/types.d.ts +6 -6
- package/dist/types.d.ts +17 -0
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +4 -4
- package/package.json +11 -1
- package/src/config.ts +18 -0
- package/src/embedding-fallback.ts +293 -61
- package/src/host-embedding-provider.ts +84 -0
- package/src/index.ts +7 -0
- package/src/namespaces/search.ts +9 -1
- package/src/qmd.test.ts +28 -0
- package/src/search/embed-helper.ts +319 -51
- package/src/search/factory.ts +6 -2
- package/src/search/lancedb-backend.ts +297 -41
- package/src/search/orama-backend.ts +418 -47
- package/src/types.ts +17 -0
- package/dist/chunk-6URPAY2D.js.map +0 -1
- package/dist/chunk-FUC4LZMD.js +0 -301
- package/dist/chunk-FUC4LZMD.js.map +0 -1
- package/dist/chunk-KXULCVOC.js.map +0 -1
- package/dist/chunk-M5T4Q2ZU.js.map +0 -1
- package/dist/chunk-ONPLNAPX.js +0 -133
- package/dist/chunk-ONPLNAPX.js.map +0 -1
- package/dist/chunk-QVJ4NWL2.js +0 -335
- package/dist/chunk-QVJ4NWL2.js.map +0 -1
- package/dist/chunk-SML26KED.js.map +0 -1
- /package/dist/{chunk-I2K6KCVC.js.map → chunk-2FHLI4U6.js.map} +0 -0
- /package/dist/{chunk-5GX5MUQ2.js.map → chunk-574MU2Y3.js.map} +0 -0
- /package/dist/{chunk-65OLPXBU.js.map → chunk-5WB4C7KM.js.map} +0 -0
- /package/dist/{chunk-Z56KAZQL.js.map → chunk-74VA26CT.js.map} +0 -0
- /package/dist/{chunk-CC2ESOOG.js.map → chunk-7X7TBJRX.js.map} +0 -0
- /package/dist/{chunk-O4M4WH6V.js.map → chunk-ARY5OOLG.js.map} +0 -0
- /package/dist/{chunk-JBPKEARU.js.map → chunk-AU7Q3LSC.js.map} +0 -0
- /package/dist/{chunk-PM3QHTFT.js.map → chunk-CF3ZF2YU.js.map} +0 -0
- /package/dist/{chunk-SI3QCHWF.js.map → chunk-DARLGSFX.js.map} +0 -0
- /package/dist/{chunk-FVCZINOF.js.map → chunk-FHBEL473.js.map} +0 -0
- /package/dist/{chunk-7Q3RCKAQ.js.map → chunk-FXKPZ3H6.js.map} +0 -0
- /package/dist/{chunk-5WLYNZPC.js.map → chunk-GBXGCFRH.js.map} +0 -0
- /package/dist/{chunk-ILJXM3FV.js.map → chunk-HQO5EBUC.js.map} +0 -0
- /package/dist/{chunk-FK556DDH.js.map → chunk-I4UNL747.js.map} +0 -0
- /package/dist/{chunk-RLPIT4YI.js.map → chunk-IOTTZLFF.js.map} +0 -0
- /package/dist/{chunk-TVZ6LKKS.js.map → chunk-IRFF6LSF.js.map} +0 -0
- /package/dist/{chunk-IPLYGWQF.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-JFN6K74Q.js.map → chunk-MQEIWDYW.js.map} +0 -0
- /package/dist/{chunk-SOTR74FK.js.map → chunk-OPYFD6PD.js.map} +0 -0
- /package/dist/{chunk-3C5RPJAX.js.map → chunk-OXJBNGBK.js.map} +0 -0
- /package/dist/{chunk-BD5LHQWD.js.map → chunk-PPPZY2EU.js.map} +0 -0
- /package/dist/{chunk-25BY3HHZ.js.map → chunk-SUTSSOYU.js.map} +0 -0
- /package/dist/{chunk-KS7WO6EQ.js.map → chunk-VFB2G5YL.js.map} +0 -0
- /package/dist/{chunk-BUUYY2H2.js.map → chunk-WP5OWVLZ.js.map} +0 -0
- /package/dist/{chunk-S53PAX2V.js.map → chunk-XM7BYXT7.js.map} +0 -0
- /package/dist/{chunk-FADZBOR4.js.map → chunk-XRWTAEZM.js.map} +0 -0
- /package/dist/{chunk-E5OECWZ5.js.map → chunk-XT7XVA53.js.map} +0 -0
- /package/dist/{chunk-R3PS27B4.js.map → chunk-Z4R6RI2N.js.map} +0 -0
package/dist/chunk-QVJ4NWL2.js
DELETED
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
scanMemoryDir
|
|
3
|
-
} from "./chunk-Q4CAQGKQ.js";
|
|
4
|
-
import {
|
|
5
|
-
isSearchAborted,
|
|
6
|
-
throwIfSearchAborted
|
|
7
|
-
} from "./chunk-CINZGPSJ.js";
|
|
8
|
-
import {
|
|
9
|
-
log
|
|
10
|
-
} from "./chunk-2ODBA7MQ.js";
|
|
11
|
-
|
|
12
|
-
// src/search/orama-backend.ts
|
|
13
|
-
import path from "path";
|
|
14
|
-
import { mkdir, readdir, readFile, writeFile } from "fs/promises";
|
|
15
|
-
var ORAMA_COLLECTION_FILENAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
16
|
-
function pathIsInside(parent, child) {
|
|
17
|
-
const relative = path.relative(parent, child);
|
|
18
|
-
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
19
|
-
}
|
|
20
|
-
function resolveOramaCollectionDbFilePath(dbPath, collection) {
|
|
21
|
-
if (!ORAMA_COLLECTION_FILENAME_PATTERN.test(collection)) {
|
|
22
|
-
throw new Error(
|
|
23
|
-
`Invalid Orama collection name ${JSON.stringify(collection)}. Collection names must match [A-Za-z0-9][A-Za-z0-9._-]*.`
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
const resolvedDbPath = path.resolve(dbPath);
|
|
27
|
-
const filePath = path.resolve(resolvedDbPath, `${collection}.msp`);
|
|
28
|
-
if (!pathIsInside(resolvedDbPath, filePath)) {
|
|
29
|
-
throw new Error(
|
|
30
|
-
`Invalid Orama collection path for ${JSON.stringify(collection)}: resolved outside dbPath.`
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
return filePath;
|
|
34
|
-
}
|
|
35
|
-
var OramaBackend = class {
|
|
36
|
-
dbPath;
|
|
37
|
-
collection;
|
|
38
|
-
embedHelper;
|
|
39
|
-
memoryDir;
|
|
40
|
-
embeddingDimension;
|
|
41
|
-
available = false;
|
|
42
|
-
db = null;
|
|
43
|
-
oramaModule = null;
|
|
44
|
-
persistModule = null;
|
|
45
|
-
constructor(opts) {
|
|
46
|
-
this.dbPath = opts.dbPath;
|
|
47
|
-
this.collection = opts.collection;
|
|
48
|
-
this.embedHelper = opts.embedHelper;
|
|
49
|
-
this.memoryDir = opts.memoryDir;
|
|
50
|
-
this.embeddingDimension = opts.embeddingDimension;
|
|
51
|
-
}
|
|
52
|
-
async probe() {
|
|
53
|
-
try {
|
|
54
|
-
await this.ensureModules();
|
|
55
|
-
await this.ensureDb();
|
|
56
|
-
this.available = true;
|
|
57
|
-
return true;
|
|
58
|
-
} catch (err) {
|
|
59
|
-
log.debug(`OramaBackend probe failed: ${err}`);
|
|
60
|
-
this.available = false;
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
isAvailable() {
|
|
65
|
-
return this.available;
|
|
66
|
-
}
|
|
67
|
-
debugStatus() {
|
|
68
|
-
return `backend=orama available=${this.available} dbPath=${this.dbPath}`;
|
|
69
|
-
}
|
|
70
|
-
async search(query, _collection, maxResults, _options, execution) {
|
|
71
|
-
return this.hybridSearch(query, _collection, maxResults, execution);
|
|
72
|
-
}
|
|
73
|
-
async searchGlobal(query, maxResults, execution) {
|
|
74
|
-
const limit = maxResults ?? 10;
|
|
75
|
-
if (!this.available) return [];
|
|
76
|
-
try {
|
|
77
|
-
throwIfSearchAborted(execution, "OramaBackend global search aborted");
|
|
78
|
-
const files = await this.listDbFiles();
|
|
79
|
-
const allResults = [];
|
|
80
|
-
for (const file of files) {
|
|
81
|
-
throwIfSearchAborted(execution, "OramaBackend global search aborted");
|
|
82
|
-
const db = await this.loadDbFromFile(file);
|
|
83
|
-
if (!db) continue;
|
|
84
|
-
const results = await this.searchDb(db, query, "hybrid", limit, execution);
|
|
85
|
-
allResults.push(...results);
|
|
86
|
-
}
|
|
87
|
-
allResults.sort((a, b) => b.score - a.score);
|
|
88
|
-
return allResults.slice(0, limit);
|
|
89
|
-
} catch (err) {
|
|
90
|
-
log.debug(`OramaBackend searchGlobal failed: ${err}`);
|
|
91
|
-
return [];
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
async bm25Search(query, collection, maxResults, execution) {
|
|
95
|
-
if (isSearchAborted(execution)) return [];
|
|
96
|
-
const db = await this.ensureDbForCollection(collection ?? this.collection);
|
|
97
|
-
if (isSearchAborted(execution)) return [];
|
|
98
|
-
if (!db) return [];
|
|
99
|
-
return this.searchDb(db, query, "fulltext", maxResults ?? 10, execution);
|
|
100
|
-
}
|
|
101
|
-
async vectorSearch(query, collection, maxResults, execution) {
|
|
102
|
-
if (isSearchAborted(execution)) return [];
|
|
103
|
-
const db = await this.ensureDbForCollection(collection ?? this.collection);
|
|
104
|
-
if (isSearchAborted(execution)) return [];
|
|
105
|
-
if (!db) return [];
|
|
106
|
-
return this.searchDb(db, query, "vector", maxResults ?? 10, execution);
|
|
107
|
-
}
|
|
108
|
-
async hybridSearch(query, collection, maxResults, execution) {
|
|
109
|
-
if (isSearchAborted(execution)) return [];
|
|
110
|
-
const db = await this.ensureDbForCollection(collection ?? this.collection);
|
|
111
|
-
if (isSearchAborted(execution)) return [];
|
|
112
|
-
if (!db) return [];
|
|
113
|
-
return this.searchDb(db, query, "hybrid", maxResults ?? 10, execution);
|
|
114
|
-
}
|
|
115
|
-
async update(execution) {
|
|
116
|
-
await this.updateCollection(this.collection, execution);
|
|
117
|
-
}
|
|
118
|
-
async updateCollection(collection, execution) {
|
|
119
|
-
if (isSearchAborted(execution)) return;
|
|
120
|
-
const db = await this.ensureDbForCollection(collection);
|
|
121
|
-
if (isSearchAborted(execution)) return;
|
|
122
|
-
if (!db) return;
|
|
123
|
-
const { search: oramaSearch, insert, remove, count } = this.oramaModule;
|
|
124
|
-
const docs = await scanMemoryDir(this.memoryDir);
|
|
125
|
-
if (isSearchAborted(execution)) return;
|
|
126
|
-
const docMap = new Map(docs.map((d) => [d.docid, d]));
|
|
127
|
-
const { update: oramaUpdate } = this.oramaModule;
|
|
128
|
-
const existingDocs = /* @__PURE__ */ new Map();
|
|
129
|
-
const existingCount = await count(db);
|
|
130
|
-
if (existingCount > 0) {
|
|
131
|
-
const allHits = await oramaSearch(db, { term: "", limit: existingCount + 100 });
|
|
132
|
-
for (const hit of allHits.hits) {
|
|
133
|
-
if (isSearchAborted(execution)) return;
|
|
134
|
-
if (!docMap.has(hit.document.id)) {
|
|
135
|
-
await remove(db, hit.id);
|
|
136
|
-
} else {
|
|
137
|
-
existingDocs.set(hit.document.id, {
|
|
138
|
-
internalId: hit.id,
|
|
139
|
-
vector: hit.document.vector
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
for (const doc of docs) {
|
|
145
|
-
if (isSearchAborted(execution)) return;
|
|
146
|
-
const existing = existingDocs.get(doc.docid);
|
|
147
|
-
if (existing) {
|
|
148
|
-
const payload = {
|
|
149
|
-
id: doc.docid,
|
|
150
|
-
path: doc.path,
|
|
151
|
-
content: doc.content,
|
|
152
|
-
snippet: doc.snippet
|
|
153
|
-
};
|
|
154
|
-
if (existing.vector && existing.vector.length > 0) {
|
|
155
|
-
payload.vector = existing.vector;
|
|
156
|
-
}
|
|
157
|
-
try {
|
|
158
|
-
await oramaUpdate(db, existing.internalId, payload);
|
|
159
|
-
} catch {
|
|
160
|
-
}
|
|
161
|
-
} else {
|
|
162
|
-
try {
|
|
163
|
-
await insert(db, {
|
|
164
|
-
id: doc.docid,
|
|
165
|
-
path: doc.path,
|
|
166
|
-
content: doc.content,
|
|
167
|
-
snippet: doc.snippet
|
|
168
|
-
});
|
|
169
|
-
} catch {
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (isSearchAborted(execution)) return;
|
|
174
|
-
await this.persistDbForCollection(db, collection);
|
|
175
|
-
}
|
|
176
|
-
async embed() {
|
|
177
|
-
await this.embedCollection(this.collection);
|
|
178
|
-
}
|
|
179
|
-
async embedCollection(collection) {
|
|
180
|
-
if (!this.embedHelper.isAvailable()) return;
|
|
181
|
-
const db = await this.ensureDbForCollection(collection);
|
|
182
|
-
if (!db) return;
|
|
183
|
-
const { search: oramaSearch, update: oramaUpdate, count } = this.oramaModule;
|
|
184
|
-
const existingCount = await count(db);
|
|
185
|
-
if (existingCount === 0) return;
|
|
186
|
-
const allHits = await oramaSearch(db, { term: "", limit: existingCount + 100 });
|
|
187
|
-
const needsEmbed = allHits.hits.filter((h) => !h.document.vector || h.document.vector.length === 0);
|
|
188
|
-
if (needsEmbed.length === 0) return;
|
|
189
|
-
const texts = needsEmbed.map((h) => h.document.content);
|
|
190
|
-
const vectors = await this.embedHelper.embedBatch(texts);
|
|
191
|
-
for (let i = 0; i < needsEmbed.length; i++) {
|
|
192
|
-
const vec = vectors[i];
|
|
193
|
-
if (!vec) continue;
|
|
194
|
-
const doc = needsEmbed[i].document;
|
|
195
|
-
await oramaUpdate(db, needsEmbed[i].id, {
|
|
196
|
-
id: doc.id,
|
|
197
|
-
path: doc.path,
|
|
198
|
-
content: doc.content,
|
|
199
|
-
snippet: doc.snippet,
|
|
200
|
-
vector: vec
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
await this.persistDbForCollection(db, collection);
|
|
204
|
-
}
|
|
205
|
-
async ensureCollection(_memoryDir, _execution) {
|
|
206
|
-
try {
|
|
207
|
-
await this.ensureModules();
|
|
208
|
-
await this.ensureDb();
|
|
209
|
-
return "present";
|
|
210
|
-
} catch {
|
|
211
|
-
return "missing";
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
async ensureModules() {
|
|
215
|
-
if (this.oramaModule && this.persistModule) return;
|
|
216
|
-
this.oramaModule = await import("@orama/orama");
|
|
217
|
-
this.persistModule = await import("@orama/plugin-data-persistence");
|
|
218
|
-
}
|
|
219
|
-
async ensureDb() {
|
|
220
|
-
if (this.db) return this.db;
|
|
221
|
-
await this.ensureModules();
|
|
222
|
-
await mkdir(this.dbPath, { recursive: true });
|
|
223
|
-
const filePath = this.dbFilePath(this.collection);
|
|
224
|
-
try {
|
|
225
|
-
const raw = await readFile(filePath, "utf-8");
|
|
226
|
-
this.db = await this.persistModule.restore("json", raw);
|
|
227
|
-
return this.db;
|
|
228
|
-
} catch {
|
|
229
|
-
}
|
|
230
|
-
const { create } = this.oramaModule;
|
|
231
|
-
const schema = {
|
|
232
|
-
id: "string",
|
|
233
|
-
path: "string",
|
|
234
|
-
content: "string",
|
|
235
|
-
snippet: "string"
|
|
236
|
-
};
|
|
237
|
-
if (this.embedHelper.isAvailable()) {
|
|
238
|
-
schema.vector = `vector[${this.embeddingDimension}]`;
|
|
239
|
-
}
|
|
240
|
-
this.db = await create({ schema });
|
|
241
|
-
return this.db;
|
|
242
|
-
}
|
|
243
|
-
async ensureDbForCollection(collection) {
|
|
244
|
-
if (collection === this.collection) return this.ensureDb();
|
|
245
|
-
await this.ensureModules();
|
|
246
|
-
await mkdir(this.dbPath, { recursive: true });
|
|
247
|
-
const filePath = this.dbFilePath(collection);
|
|
248
|
-
try {
|
|
249
|
-
const raw = await readFile(filePath, "utf-8");
|
|
250
|
-
return await this.persistModule.restore("json", raw);
|
|
251
|
-
} catch {
|
|
252
|
-
}
|
|
253
|
-
const { create } = this.oramaModule;
|
|
254
|
-
const schema = {
|
|
255
|
-
id: "string",
|
|
256
|
-
path: "string",
|
|
257
|
-
content: "string",
|
|
258
|
-
snippet: "string"
|
|
259
|
-
};
|
|
260
|
-
if (this.embedHelper.isAvailable()) {
|
|
261
|
-
schema.vector = `vector[${this.embeddingDimension}]`;
|
|
262
|
-
}
|
|
263
|
-
return await create({ schema });
|
|
264
|
-
}
|
|
265
|
-
async persistDbForCollection(db, collection) {
|
|
266
|
-
const data = await this.persistModule.persist(db, "json");
|
|
267
|
-
const filePath = this.dbFilePath(collection);
|
|
268
|
-
await mkdir(path.dirname(filePath), { recursive: true });
|
|
269
|
-
await writeFile(filePath, data, "utf-8");
|
|
270
|
-
}
|
|
271
|
-
dbFilePath(collection) {
|
|
272
|
-
return resolveOramaCollectionDbFilePath(this.dbPath, collection);
|
|
273
|
-
}
|
|
274
|
-
async listDbFiles() {
|
|
275
|
-
try {
|
|
276
|
-
const entries = await readdir(this.dbPath);
|
|
277
|
-
return entries.filter((e) => e.endsWith(".msp")).map((e) => path.join(this.dbPath, e));
|
|
278
|
-
} catch {
|
|
279
|
-
return [];
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
async loadDbFromFile(filePath) {
|
|
283
|
-
try {
|
|
284
|
-
await this.ensureModules();
|
|
285
|
-
const raw = await readFile(filePath, "utf-8");
|
|
286
|
-
return await this.persistModule.restore("json", raw);
|
|
287
|
-
} catch {
|
|
288
|
-
return null;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
async searchDb(db, query, mode, limit, execution) {
|
|
292
|
-
const { search: oramaSearch } = this.oramaModule;
|
|
293
|
-
try {
|
|
294
|
-
throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);
|
|
295
|
-
let searchParams;
|
|
296
|
-
if (mode === "fulltext") {
|
|
297
|
-
searchParams = { term: query, limit };
|
|
298
|
-
} else if (mode === "vector") {
|
|
299
|
-
const vec = await this.embedHelper.embed(query, { signal: execution?.signal });
|
|
300
|
-
throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);
|
|
301
|
-
if (!vec) {
|
|
302
|
-
searchParams = { term: query, limit };
|
|
303
|
-
} else {
|
|
304
|
-
searchParams = { mode: "vector", vector: { value: vec, property: "vector" }, limit };
|
|
305
|
-
}
|
|
306
|
-
} else {
|
|
307
|
-
const vec = await this.embedHelper.embed(query, { signal: execution?.signal });
|
|
308
|
-
throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);
|
|
309
|
-
if (!vec) {
|
|
310
|
-
searchParams = { term: query, limit };
|
|
311
|
-
} else {
|
|
312
|
-
searchParams = { mode: "hybrid", term: query, vector: { value: vec, property: "vector" }, limit };
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);
|
|
316
|
-
const result = await oramaSearch(db, searchParams);
|
|
317
|
-
throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);
|
|
318
|
-
return (result.hits ?? []).map((hit) => ({
|
|
319
|
-
docid: hit.document?.id ?? "",
|
|
320
|
-
path: hit.document?.path ?? "",
|
|
321
|
-
snippet: hit.document?.snippet ?? hit.document?.content?.slice(0, 200) ?? "",
|
|
322
|
-
score: hit.score ?? 0
|
|
323
|
-
}));
|
|
324
|
-
} catch (err) {
|
|
325
|
-
log.debug(`OramaBackend search (${mode}) failed: ${err}`);
|
|
326
|
-
return [];
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
export {
|
|
332
|
-
resolveOramaCollectionDbFilePath,
|
|
333
|
-
OramaBackend
|
|
334
|
-
};
|
|
335
|
-
//# sourceMappingURL=chunk-QVJ4NWL2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/search/orama-backend.ts"],"sourcesContent":["import path from \"node:path\";\nimport { mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport { log } from \"../logger.js\";\nimport type { SearchBackend, SearchExecutionOptions, SearchQueryOptions, SearchResult } from \"./port.js\";\nimport type { EmbedHelper } from \"./embed-helper.js\";\nimport { scanMemoryDir } from \"./document-scanner.js\";\nimport { isSearchAborted, throwIfSearchAborted } from \"./abort.js\";\n\nexport interface OramaBackendOptions {\n dbPath: string;\n collection: string;\n embedHelper: EmbedHelper;\n memoryDir: string;\n embeddingDimension: number;\n}\n\nconst ORAMA_COLLECTION_FILENAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\nfunction pathIsInside(parent: string, child: string): boolean {\n const relative = path.relative(parent, child);\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nexport function resolveOramaCollectionDbFilePath(dbPath: string, collection: string): string {\n if (!ORAMA_COLLECTION_FILENAME_PATTERN.test(collection)) {\n throw new Error(\n `Invalid Orama collection name ${JSON.stringify(collection)}. ` +\n \"Collection names must match [A-Za-z0-9][A-Za-z0-9._-]*.\",\n );\n }\n const resolvedDbPath = path.resolve(dbPath);\n const filePath = path.resolve(resolvedDbPath, `${collection}.msp`);\n if (!pathIsInside(resolvedDbPath, filePath)) {\n throw new Error(\n `Invalid Orama collection path for ${JSON.stringify(collection)}: resolved outside dbPath.`,\n );\n }\n return filePath;\n}\n\n/**\n * Orama search backend — embedded hybrid FTS+vector, pure JS.\n *\n * Uses @orama/orama for full-text search with optional vector support.\n * Persists data to JSON files via @orama/plugin-data-persistence.\n */\nexport class OramaBackend implements SearchBackend {\n private readonly dbPath: string;\n private readonly collection: string;\n private readonly embedHelper: EmbedHelper;\n private readonly memoryDir: string;\n private readonly embeddingDimension: number;\n private available = false;\n private db: any = null;\n private oramaModule: any = null;\n private persistModule: any = null;\n\n constructor(opts: OramaBackendOptions) {\n this.dbPath = opts.dbPath;\n this.collection = opts.collection;\n this.embedHelper = opts.embedHelper;\n this.memoryDir = opts.memoryDir;\n this.embeddingDimension = opts.embeddingDimension;\n }\n\n async probe(): Promise<boolean> {\n try {\n await this.ensureModules();\n await this.ensureDb();\n this.available = true;\n return true;\n } catch (err) {\n log.debug(`OramaBackend probe failed: ${err}`);\n this.available = false;\n return false;\n }\n }\n\n isAvailable(): boolean {\n return this.available;\n }\n\n debugStatus(): string {\n return `backend=orama available=${this.available} dbPath=${this.dbPath}`;\n }\n\n async search(\n query: string,\n _collection?: string,\n maxResults?: number,\n _options?: SearchQueryOptions,\n execution?: SearchExecutionOptions,\n ): Promise<SearchResult[]> {\n return this.hybridSearch(query, _collection, maxResults, execution);\n }\n\n async searchGlobal(query: string, maxResults?: number, execution?: SearchExecutionOptions): Promise<SearchResult[]> {\n const limit = maxResults ?? 10;\n if (!this.available) return [];\n try {\n throwIfSearchAborted(execution, \"OramaBackend global search aborted\");\n const files = await this.listDbFiles();\n const allResults: SearchResult[] = [];\n for (const file of files) {\n throwIfSearchAborted(execution, \"OramaBackend global search aborted\");\n const db = await this.loadDbFromFile(file);\n if (!db) continue;\n const results = await this.searchDb(db, query, \"hybrid\", limit, execution);\n allResults.push(...results);\n }\n allResults.sort((a, b) => b.score - a.score);\n return allResults.slice(0, limit);\n } catch (err) {\n log.debug(`OramaBackend searchGlobal failed: ${err}`);\n return [];\n }\n }\n\n async bm25Search(query: string, collection?: string, maxResults?: number, execution?: SearchExecutionOptions): Promise<SearchResult[]> {\n if (isSearchAborted(execution)) return [];\n const db = await this.ensureDbForCollection(collection ?? this.collection);\n if (isSearchAborted(execution)) return [];\n if (!db) return [];\n return this.searchDb(db, query, \"fulltext\", maxResults ?? 10, execution);\n }\n\n async vectorSearch(query: string, collection?: string, maxResults?: number, execution?: SearchExecutionOptions): Promise<SearchResult[]> {\n if (isSearchAborted(execution)) return [];\n const db = await this.ensureDbForCollection(collection ?? this.collection);\n if (isSearchAborted(execution)) return [];\n if (!db) return [];\n return this.searchDb(db, query, \"vector\", maxResults ?? 10, execution);\n }\n\n async hybridSearch(query: string, collection?: string, maxResults?: number, execution?: SearchExecutionOptions): Promise<SearchResult[]> {\n if (isSearchAborted(execution)) return [];\n const db = await this.ensureDbForCollection(collection ?? this.collection);\n if (isSearchAborted(execution)) return [];\n if (!db) return [];\n return this.searchDb(db, query, \"hybrid\", maxResults ?? 10, execution);\n }\n\n async update(execution?: SearchExecutionOptions): Promise<void> {\n await this.updateCollection(this.collection, execution);\n }\n\n async updateCollection(collection: string, execution?: SearchExecutionOptions): Promise<void> {\n if (isSearchAborted(execution)) return;\n const db = await this.ensureDbForCollection(collection);\n if (isSearchAborted(execution)) return;\n if (!db) return;\n const { search: oramaSearch, insert, remove, count } = this.oramaModule;\n\n const docs = await scanMemoryDir(this.memoryDir);\n if (isSearchAborted(execution)) return;\n const docMap = new Map(docs.map((d) => [d.docid, d]));\n const { update: oramaUpdate } = this.oramaModule;\n\n // Get existing docs to diff — map user doc ID → { internalId, vector }\n const existingDocs = new Map<string, { internalId: string; vector?: number[] }>();\n const existingCount = await count(db);\n if (existingCount > 0) {\n const allHits = await oramaSearch(db, { term: \"\", limit: existingCount + 100 });\n for (const hit of allHits.hits) {\n if (isSearchAborted(execution)) return;\n if (!docMap.has(hit.document.id)) {\n await remove(db, hit.id);\n } else {\n existingDocs.set(hit.document.id, {\n internalId: hit.id,\n vector: hit.document.vector,\n });\n }\n }\n }\n\n // Insert new docs, update existing ones (preserving vectors since update is remove+insert)\n for (const doc of docs) {\n if (isSearchAborted(execution)) return;\n const existing = existingDocs.get(doc.docid);\n if (existing) {\n const payload: Record<string, unknown> = {\n id: doc.docid,\n path: doc.path,\n content: doc.content,\n snippet: doc.snippet,\n };\n if (existing.vector && existing.vector.length > 0) {\n payload.vector = existing.vector;\n }\n try {\n await oramaUpdate(db, existing.internalId, payload);\n } catch {\n // Update failed — skip and continue with remaining docs\n }\n } else {\n try {\n await insert(db, {\n id: doc.docid,\n path: doc.path,\n content: doc.content,\n snippet: doc.snippet,\n });\n } catch {\n // Duplicate id edge case — skip\n }\n }\n }\n\n if (isSearchAborted(execution)) return;\n await this.persistDbForCollection(db, collection);\n }\n\n async embed(): Promise<void> {\n await this.embedCollection(this.collection);\n }\n\n async embedCollection(collection: string): Promise<void> {\n if (!this.embedHelper.isAvailable()) return;\n\n const db = await this.ensureDbForCollection(collection);\n if (!db) return;\n const { search: oramaSearch, update: oramaUpdate, count } = this.oramaModule;\n\n const existingCount = await count(db);\n if (existingCount === 0) return;\n\n // Find docs without vectors\n const allHits = await oramaSearch(db, { term: \"\", limit: existingCount + 100 });\n const needsEmbed = allHits.hits.filter((h: any) => !h.document.vector || h.document.vector.length === 0);\n\n if (needsEmbed.length === 0) return;\n\n const texts = needsEmbed.map((h: any) => h.document.content as string);\n const vectors = await this.embedHelper.embedBatch(texts);\n\n for (let i = 0; i < needsEmbed.length; i++) {\n const vec = vectors[i];\n if (!vec) continue;\n // Orama update is remove+insert — must include all fields to avoid data loss\n const doc = needsEmbed[i].document;\n await oramaUpdate(db, needsEmbed[i].id, {\n id: doc.id,\n path: doc.path,\n content: doc.content,\n snippet: doc.snippet,\n vector: vec,\n });\n }\n\n await this.persistDbForCollection(db, collection);\n }\n\n async ensureCollection(\n _memoryDir: string,\n _execution?: SearchExecutionOptions,\n ): Promise<\"present\" | \"missing\" | \"unknown\" | \"skipped\"> {\n try {\n await this.ensureModules();\n await this.ensureDb();\n return \"present\";\n } catch {\n return \"missing\";\n }\n }\n\n private async ensureModules(): Promise<void> {\n if (this.oramaModule && this.persistModule) return;\n this.oramaModule = await import(\"@orama/orama\");\n this.persistModule = await import(\"@orama/plugin-data-persistence\");\n }\n\n private async ensureDb(): Promise<any> {\n if (this.db) return this.db;\n await this.ensureModules();\n\n await mkdir(this.dbPath, { recursive: true });\n const filePath = this.dbFilePath(this.collection);\n\n try {\n const raw = await readFile(filePath, \"utf-8\");\n this.db = await this.persistModule.restore(\"json\", raw);\n return this.db;\n } catch {\n // No existing DB — create fresh\n }\n\n const { create } = this.oramaModule;\n const schema: Record<string, string> = {\n id: \"string\",\n path: \"string\",\n content: \"string\",\n snippet: \"string\",\n };\n if (this.embedHelper.isAvailable()) {\n schema.vector = `vector[${this.embeddingDimension}]`;\n }\n this.db = await create({ schema });\n return this.db;\n }\n\n private async ensureDbForCollection(collection: string): Promise<any> {\n // For the default collection, use the cached instance\n if (collection === this.collection) return this.ensureDb();\n\n await this.ensureModules();\n await mkdir(this.dbPath, { recursive: true });\n const filePath = this.dbFilePath(collection);\n\n try {\n const raw = await readFile(filePath, \"utf-8\");\n return await this.persistModule.restore(\"json\", raw);\n } catch {\n // No existing DB — create fresh\n }\n\n const { create } = this.oramaModule;\n const schema: Record<string, string> = {\n id: \"string\",\n path: \"string\",\n content: \"string\",\n snippet: \"string\",\n };\n if (this.embedHelper.isAvailable()) {\n schema.vector = `vector[${this.embeddingDimension}]`;\n }\n return await create({ schema });\n }\n\n private async persistDbForCollection(db: any, collection: string): Promise<void> {\n const data = await this.persistModule.persist(db, \"json\");\n const filePath = this.dbFilePath(collection);\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(filePath, data, \"utf-8\");\n }\n\n private dbFilePath(collection: string): string {\n return resolveOramaCollectionDbFilePath(this.dbPath, collection);\n }\n\n private async listDbFiles(): Promise<string[]> {\n try {\n const entries = await readdir(this.dbPath);\n return entries\n .filter((e) => e.endsWith(\".msp\"))\n .map((e) => path.join(this.dbPath, e));\n } catch {\n return [];\n }\n }\n\n private async loadDbFromFile(filePath: string): Promise<any> {\n try {\n await this.ensureModules();\n const raw = await readFile(filePath, \"utf-8\");\n return await this.persistModule.restore(\"json\", raw);\n } catch {\n return null;\n }\n }\n\n private async searchDb(\n db: any,\n query: string,\n mode: \"fulltext\" | \"vector\" | \"hybrid\",\n limit: number,\n execution?: SearchExecutionOptions,\n ): Promise<SearchResult[]> {\n const { search: oramaSearch } = this.oramaModule;\n\n try {\n throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);\n let searchParams: any;\n\n if (mode === \"fulltext\") {\n searchParams = { term: query, limit };\n } else if (mode === \"vector\") {\n const vec = await this.embedHelper.embed(query, { signal: execution?.signal });\n throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);\n if (!vec) {\n // Fall back to fulltext if no embeddings available\n searchParams = { term: query, limit };\n } else {\n searchParams = { mode: \"vector\", vector: { value: vec, property: \"vector\" }, limit };\n }\n } else {\n // hybrid\n const vec = await this.embedHelper.embed(query, { signal: execution?.signal });\n throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);\n if (!vec) {\n searchParams = { term: query, limit };\n } else {\n searchParams = { mode: \"hybrid\", term: query, vector: { value: vec, property: \"vector\" }, limit };\n }\n }\n\n throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);\n const result = await oramaSearch(db, searchParams);\n throwIfSearchAborted(execution, `OramaBackend ${mode} search aborted`);\n return (result.hits ?? []).map((hit: any) => ({\n docid: hit.document?.id ?? \"\",\n path: hit.document?.path ?? \"\",\n snippet: hit.document?.snippet ?? hit.document?.content?.slice(0, 200) ?? \"\",\n score: hit.score ?? 0,\n }));\n } catch (err) {\n log.debug(`OramaBackend search (${mode}) failed: ${err}`);\n return [];\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/search/factory.ts"],"sourcesContent":["import type { PluginConfig } from \"../types.js\";\nimport type { SearchBackend } from \"./port.js\";\nimport path from \"node:path\";\nimport { NoopSearchBackend } from \"./noop-backend.js\";\nimport { RemoteSearchBackend } from \"./remote-backend.js\";\nimport { LanceDbBackend } from \"./lancedb-backend.js\";\nimport { MeilisearchBackend } from \"./meilisearch-backend.js\";\nimport { OramaBackend } from \"./orama-backend.js\";\nimport { EmbedHelper } from \"./embed-helper.js\";\nimport { QmdClient, type QmdClientOptions } from \"../qmd.js\";\nimport { log } from \"../logger.js\";\nimport { FaissConversationIndexAdapter } from \"../conversation-index/faiss-adapter.js\";\nimport {\n createConversationIndexBackend,\n type ConversationIndexBackend,\n type ConversationQmdRuntime,\n} from \"../conversation-index/backend.js\";\n\n/**\n * Resolve non-QMD backends from config.\n * Returns a SearchBackend for \"noop\" or \"remote\", or undefined to signal \"use QMD\".\n */\nfunction resolveNonQmdBackend(config: PluginConfig): SearchBackend | undefined {\n const backend = config.searchBackend ?? \"qmd\";\n const collection = config.qmdCollection;\n\n if (backend === \"noop\") {\n return new NoopSearchBackend();\n }\n\n if (backend === \"remote\") {\n const baseUrl = config.remoteSearchBaseUrl || \"http://localhost:8181\";\n if (!config.remoteSearchBaseUrl) {\n log.warn(\"searchBackend is 'remote' but remoteSearchBaseUrl is not configured; using default http://localhost:8181\");\n }\n return new RemoteSearchBackend({\n baseUrl,\n apiKey: config.remoteSearchApiKey,\n timeoutMs: config.remoteSearchTimeoutMs,\n });\n }\n\n if (backend === \"lancedb\") {\n const embedHelper = new EmbedHelper(config);\n return new LanceDbBackend({\n dbPath: config.lanceDbPath!,\n collection,\n embedHelper,\n memoryDir: config.memoryDir,\n embeddingDimension: config.lanceEmbeddingDimension!,\n });\n }\n\n if (backend === \"meilisearch\") {\n return new MeilisearchBackend({\n host: config.meilisearchHost!,\n apiKey: config.meilisearchApiKey,\n collection,\n timeoutMs: config.meilisearchTimeoutMs,\n autoIndex: config.meilisearchAutoIndex,\n memoryDir: config.memoryDir,\n });\n }\n\n if (backend === \"orama\") {\n const embedHelper = new EmbedHelper(config);\n return new OramaBackend({\n dbPath: config.oramaDbPath!,\n collection,\n embedHelper,\n memoryDir: config.memoryDir,\n embeddingDimension: config.oramaEmbeddingDimension!,\n });\n }\n\n return undefined;\n}\n\n/** Shared QMD options derived from plugin config. */\nfunction qmdOptions(config: PluginConfig): QmdClientOptions {\n return {\n slowLog: {\n enabled: config.slowLogEnabled,\n thresholdMs: config.slowLogThresholdMs,\n },\n updateTimeoutMs: config.qmdUpdateTimeoutMs,\n updateMinIntervalMs: config.qmdUpdateMinIntervalMs,\n qmdPath: config.qmdPath,\n daemonUrl: config.qmdDaemonEnabled ? config.qmdDaemonUrl : undefined,\n daemonRecheckIntervalMs: config.qmdDaemonRecheckIntervalMs,\n qmdSupportedVersion: config.qmdSupportedVersion,\n qmdAutoUpgradeEnabled: config.qmdAutoUpgradeEnabled,\n qmdAutoUpgradeCheckIntervalMs: config.qmdAutoUpgradeCheckIntervalMs,\n qmdChunkStrategy: config.qmdChunkStrategy,\n qmdCandidateLimit: config.qmdCandidateLimit,\n qmdQueryRerankEnabled: config.qmdQueryRerankEnabled,\n qmdIndexName: config.qmdIndexName,\n qmdForceCpu: config.qmdForceCpu,\n qmdGpuBackend: config.qmdGpuBackend,\n qmdEmbedParallelism: config.qmdEmbedParallelism,\n qmdEmbedModel: config.qmdEmbedModel,\n qmdRerankModel: config.qmdRerankModel,\n qmdGenerateModel: config.qmdGenerateModel,\n };\n}\n\n/**\n * Create a SearchBackend from plugin config.\n *\n * - \"noop\" → NoopSearchBackend\n * - \"remote\" → RemoteSearchBackend (HTTP REST)\n * - \"qmd\" (default) → QmdClient if qmdEnabled, else NoopSearchBackend\n */\nexport function createSearchBackend(config: PluginConfig): SearchBackend {\n const nonQmd = resolveNonQmdBackend(config);\n if (nonQmd) return nonQmd;\n\n // Default: QMD — fall back to noop if qmdEnabled is false\n if (!config.qmdEnabled) {\n return new NoopSearchBackend();\n }\n\n return new QmdClient(config.qmdCollection, config.qmdMaxResults, qmdOptions(config));\n}\n\n/**\n * Create a SearchBackend for conversation index use.\n * Returns undefined if conversation index is not enabled or not using qmd backend.\n */\nexport function createConversationSearchBackend(config: PluginConfig): SearchBackend | undefined {\n if (!config.conversationIndexEnabled || config.conversationIndexBackend !== \"qmd\") {\n return undefined;\n }\n\n // Conversation index is QMD-only — do not use lancedb/meilisearch/orama even if\n // searchBackend is set to one of those. Only respect \"noop\" to allow disabling.\n const backend = config.searchBackend ?? \"qmd\";\n if (backend === \"noop\") return undefined;\n\n // QMD — respect qmdEnabled to avoid spawning the binary\n if (!config.qmdEnabled) return undefined;\n\n return new QmdClient(\n config.conversationIndexQmdCollection,\n Math.max(6, config.conversationRecallTopK),\n qmdOptions(config),\n );\n}\n\nexport interface ConversationIndexRuntime {\n qmd?: ConversationQmdRuntime;\n faiss?: FaissConversationIndexAdapter;\n backend?: ConversationIndexBackend;\n}\n\nexport function createConversationIndexRuntime(\n config: PluginConfig,\n overrides?: {\n getQmd?: () => ConversationQmdRuntime | undefined;\n getFaiss?: () => FaissConversationIndexAdapter | undefined;\n },\n): ConversationIndexRuntime {\n const qmd = createConversationSearchBackend(config) as ConversationQmdRuntime | undefined;\n let faiss: FaissConversationIndexAdapter | undefined;\n if (config.conversationIndexEnabled && config.conversationIndexBackend === \"faiss\") {\n try {\n faiss = new FaissConversationIndexAdapter({\n memoryDir: config.memoryDir,\n scriptPath: config.conversationIndexFaissScriptPath,\n pythonBin: config.conversationIndexFaissPythonBin,\n modelId: config.conversationIndexFaissModelId,\n indexDir: config.conversationIndexFaissIndexDir,\n upsertTimeoutMs: config.conversationIndexFaissUpsertTimeoutMs,\n searchTimeoutMs: config.conversationIndexFaissSearchTimeoutMs,\n healthTimeoutMs: config.conversationIndexFaissHealthTimeoutMs,\n maxBatchSize: config.conversationIndexFaissMaxBatchSize,\n maxSearchK: config.conversationIndexFaissMaxSearchK,\n });\n } catch (err) {\n log.warn(`Conversation index FAISS adapter disabled: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n const backend = createConversationIndexBackend({\n enabled: config.conversationIndexEnabled,\n backend: config.conversationIndexBackend,\n getQmd: () => overrides?.getQmd?.() ?? qmd,\n getFaiss: () => overrides?.getFaiss?.() ?? faiss,\n collectionDir: path.join(config.memoryDir, \"conversation-index\"),\n });\n\n return { qmd, faiss, backend };\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|