brainbank 0.1.0-beta.1
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/LICENSE +21 -0
- package/README.md +155 -0
- package/assets/architecture.png +0 -0
- package/bin/brainbank +18 -0
- package/bin/brainbank-mcp +19 -0
- package/dist/chunk-3YBCD6DI.js +117 -0
- package/dist/chunk-3YBCD6DI.js.map +1 -0
- package/dist/chunk-63GBCDS5.js +3249 -0
- package/dist/chunk-63GBCDS5.js.map +1 -0
- package/dist/chunk-DMFMTOHF.js +123 -0
- package/dist/chunk-DMFMTOHF.js.map +1 -0
- package/dist/chunk-FQYKWB2Q.js +136 -0
- package/dist/chunk-FQYKWB2Q.js.map +1 -0
- package/dist/chunk-IMJJ2VEM.js +74 -0
- package/dist/chunk-IMJJ2VEM.js.map +1 -0
- package/dist/chunk-M744PCJQ.js +43 -0
- package/dist/chunk-M744PCJQ.js.map +1 -0
- package/dist/chunk-O3J6ZIXK.js +82 -0
- package/dist/chunk-O3J6ZIXK.js.map +1 -0
- package/dist/chunk-OPH7GZ7U.js +124 -0
- package/dist/chunk-OPH7GZ7U.js.map +1 -0
- package/dist/chunk-PXEWQMN7.js +89 -0
- package/dist/chunk-PXEWQMN7.js.map +1 -0
- package/dist/chunk-RDQYDLYZ.js +69 -0
- package/dist/chunk-RDQYDLYZ.js.map +1 -0
- package/dist/chunk-VIIHPCC4.js +254 -0
- package/dist/chunk-VIIHPCC4.js.map +1 -0
- package/dist/chunk-WCQVDF3K.js +14 -0
- package/dist/chunk-WCQVDF3K.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +3076 -0
- package/dist/cli.js.map +1 -0
- package/dist/haiku-expander-YRSIPGKP.js +8 -0
- package/dist/haiku-expander-YRSIPGKP.js.map +1 -0
- package/dist/haiku-pruner-SHAXUPY6.js +8 -0
- package/dist/haiku-pruner-SHAXUPY6.js.map +1 -0
- package/dist/http-server-QUXHLWUM.js +9 -0
- package/dist/http-server-QUXHLWUM.js.map +1 -0
- package/dist/index.d.ts +2161 -0
- package/dist/index.js +357 -0
- package/dist/index.js.map +1 -0
- package/dist/local-embedding-NZQTILGV.js +8 -0
- package/dist/local-embedding-NZQTILGV.js.map +1 -0
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.js +334 -0
- package/dist/mcp.js.map +1 -0
- package/dist/openai-embedding-ZP5TSUJG.js +8 -0
- package/dist/openai-embedding-ZP5TSUJG.js.map +1 -0
- package/dist/perplexity-context-embedding-GI5PHE6X.js +9 -0
- package/dist/perplexity-context-embedding-GI5PHE6X.js.map +1 -0
- package/dist/perplexity-embedding-KZRYGJRC.js +10 -0
- package/dist/perplexity-embedding-KZRYGJRC.js.map +1 -0
- package/dist/plugin-IKQ6IRSJ.js +32 -0
- package/dist/plugin-IKQ6IRSJ.js.map +1 -0
- package/dist/resolve-ASGLBNUC.js +10 -0
- package/dist/resolve-ASGLBNUC.js.map +1 -0
- package/dist/stats-tui-ZY2NQSEA.js +1904 -0
- package/dist/stats-tui-ZY2NQSEA.js.map +1 -0
- package/package.json +96 -0
- package/src/brainbank.ts +617 -0
- package/src/cli/commands/collection.ts +77 -0
- package/src/cli/commands/context.ts +179 -0
- package/src/cli/commands/daemon.ts +100 -0
- package/src/cli/commands/docs.ts +71 -0
- package/src/cli/commands/files.ts +69 -0
- package/src/cli/commands/help.ts +77 -0
- package/src/cli/commands/index.ts +482 -0
- package/src/cli/commands/kv.ts +140 -0
- package/src/cli/commands/mcp-export.ts +273 -0
- package/src/cli/commands/mcp.ts +6 -0
- package/src/cli/commands/reembed.ts +30 -0
- package/src/cli/commands/scan.ts +336 -0
- package/src/cli/commands/search.ts +203 -0
- package/src/cli/commands/stats.ts +68 -0
- package/src/cli/commands/status.ts +47 -0
- package/src/cli/commands/watch.ts +47 -0
- package/src/cli/factory/brain-context.ts +43 -0
- package/src/cli/factory/builtin-registration.ts +87 -0
- package/src/cli/factory/config-loader.ts +77 -0
- package/src/cli/factory/index.ts +69 -0
- package/src/cli/factory/plugin-loader.ts +325 -0
- package/src/cli/index.ts +71 -0
- package/src/cli/server-client.ts +178 -0
- package/src/cli/tui/index-tui.tsx +667 -0
- package/src/cli/tui/stats-data.ts +523 -0
- package/src/cli/tui/stats-search.ts +262 -0
- package/src/cli/tui/stats-tui.tsx +1465 -0
- package/src/cli/tui/tree-scanner.ts +650 -0
- package/src/cli/utils.ts +137 -0
- package/src/config.ts +49 -0
- package/src/constants.ts +21 -0
- package/src/db/adapter.ts +112 -0
- package/src/db/metadata.ts +130 -0
- package/src/db/migrations.ts +66 -0
- package/src/db/sqlite-adapter.ts +218 -0
- package/src/db/tracker.ts +91 -0
- package/src/engine/index-api.ts +81 -0
- package/src/engine/reembed.ts +206 -0
- package/src/engine/search-api.ts +218 -0
- package/src/index.ts +154 -0
- package/src/lib/fts.ts +57 -0
- package/src/lib/languages.ts +180 -0
- package/src/lib/logger.ts +126 -0
- package/src/lib/math.ts +87 -0
- package/src/lib/provider-key.ts +20 -0
- package/src/lib/prune.ts +71 -0
- package/src/lib/rrf.ts +133 -0
- package/src/lib/write-lock.ts +108 -0
- package/src/mcp/mcp-server.ts +195 -0
- package/src/mcp/workspace-factory.ts +68 -0
- package/src/mcp/workspace-pool.ts +224 -0
- package/src/plugin.ts +381 -0
- package/src/providers/embeddings/embedding-worker-thread.ts +95 -0
- package/src/providers/embeddings/embedding-worker.ts +141 -0
- package/src/providers/embeddings/local-embedding.ts +115 -0
- package/src/providers/embeddings/openai-embedding.ts +167 -0
- package/src/providers/embeddings/perplexity-context-embedding.ts +195 -0
- package/src/providers/embeddings/perplexity-embedding.ts +165 -0
- package/src/providers/embeddings/resolve.ts +34 -0
- package/src/providers/pruners/haiku-expander.ts +166 -0
- package/src/providers/pruners/haiku-pruner.ts +112 -0
- package/src/providers/vector/hnsw-index.ts +174 -0
- package/src/providers/vector/hnsw-loader.ts +129 -0
- package/src/search/bm25-boost.ts +69 -0
- package/src/search/context-builder.ts +251 -0
- package/src/search/keyword/composite-bm25-search.ts +47 -0
- package/src/search/types.ts +37 -0
- package/src/search/vector/composite-vector-search.ts +61 -0
- package/src/search/vector/mmr.ts +64 -0
- package/src/services/collection.ts +384 -0
- package/src/services/daemon.ts +87 -0
- package/src/services/http-server.ts +336 -0
- package/src/services/kv-service.ts +64 -0
- package/src/services/plugin-registry.ts +77 -0
- package/src/services/watch.ts +340 -0
- package/src/services/webhook-server.ts +100 -0
- package/src/types.ts +493 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HttpServer
|
|
3
|
+
} from "./chunk-VIIHPCC4.js";
|
|
4
|
+
import {
|
|
5
|
+
HaikuPruner
|
|
6
|
+
} from "./chunk-PXEWQMN7.js";
|
|
7
|
+
import {
|
|
8
|
+
HaikuExpander
|
|
9
|
+
} from "./chunk-OPH7GZ7U.js";
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_PORT,
|
|
12
|
+
getServerUrl,
|
|
13
|
+
isServerRunning,
|
|
14
|
+
readPid,
|
|
15
|
+
removePid,
|
|
16
|
+
writePid
|
|
17
|
+
} from "./chunk-RDQYDLYZ.js";
|
|
18
|
+
import {
|
|
19
|
+
BrainBank,
|
|
20
|
+
Collection,
|
|
21
|
+
CompositeBM25Search,
|
|
22
|
+
CompositeVectorSearch,
|
|
23
|
+
ContextBuilder,
|
|
24
|
+
DEFAULTS,
|
|
25
|
+
HNSW,
|
|
26
|
+
HNSWIndex,
|
|
27
|
+
IGNORE_DIRS,
|
|
28
|
+
KVService,
|
|
29
|
+
SQLiteAdapter,
|
|
30
|
+
SUPPORTED_EXTENSIONS,
|
|
31
|
+
Watcher,
|
|
32
|
+
WebhookServer,
|
|
33
|
+
acquireLock,
|
|
34
|
+
bumpVersion,
|
|
35
|
+
contextFromCLI,
|
|
36
|
+
cosineSimilarity,
|
|
37
|
+
createBrain,
|
|
38
|
+
createTracker,
|
|
39
|
+
escapeLike,
|
|
40
|
+
getLanguage,
|
|
41
|
+
getVersion,
|
|
42
|
+
getVersions,
|
|
43
|
+
isIgnoredDir,
|
|
44
|
+
isIgnoredFile,
|
|
45
|
+
isSupported,
|
|
46
|
+
normalize,
|
|
47
|
+
normalizeBM25,
|
|
48
|
+
pruneResults,
|
|
49
|
+
reciprocalRankFusion,
|
|
50
|
+
releaseLock,
|
|
51
|
+
resetFactoryCache,
|
|
52
|
+
resolveConfig,
|
|
53
|
+
sanitizeFTS,
|
|
54
|
+
vecToBuffer,
|
|
55
|
+
withLock
|
|
56
|
+
} from "./chunk-63GBCDS5.js";
|
|
57
|
+
import {
|
|
58
|
+
providerKey,
|
|
59
|
+
resolveEmbedding
|
|
60
|
+
} from "./chunk-M744PCJQ.js";
|
|
61
|
+
import {
|
|
62
|
+
isBM25SearchPlugin,
|
|
63
|
+
isCoEditPlugin,
|
|
64
|
+
isContextFieldPlugin,
|
|
65
|
+
isContextFormatterPlugin,
|
|
66
|
+
isDocsPlugin,
|
|
67
|
+
isExpandablePlugin,
|
|
68
|
+
isFileResolvable,
|
|
69
|
+
isIndexable,
|
|
70
|
+
isMigratable,
|
|
71
|
+
isReembeddable,
|
|
72
|
+
isSearchable,
|
|
73
|
+
isVectorSearchPlugin,
|
|
74
|
+
isWatchable
|
|
75
|
+
} from "./chunk-IMJJ2VEM.js";
|
|
76
|
+
import {
|
|
77
|
+
OpenAIEmbedding
|
|
78
|
+
} from "./chunk-DMFMTOHF.js";
|
|
79
|
+
import {
|
|
80
|
+
PerplexityContextEmbedding
|
|
81
|
+
} from "./chunk-FQYKWB2Q.js";
|
|
82
|
+
import {
|
|
83
|
+
PerplexityEmbedding
|
|
84
|
+
} from "./chunk-3YBCD6DI.js";
|
|
85
|
+
import {
|
|
86
|
+
LocalEmbedding
|
|
87
|
+
} from "./chunk-O3J6ZIXK.js";
|
|
88
|
+
import {
|
|
89
|
+
__name
|
|
90
|
+
} from "./chunk-WCQVDF3K.js";
|
|
91
|
+
|
|
92
|
+
// src/types.ts
|
|
93
|
+
function isCodeResult(r) {
|
|
94
|
+
return r.type === "code";
|
|
95
|
+
}
|
|
96
|
+
__name(isCodeResult, "isCodeResult");
|
|
97
|
+
function isCommitResult(r) {
|
|
98
|
+
return r.type === "commit";
|
|
99
|
+
}
|
|
100
|
+
__name(isCommitResult, "isCommitResult");
|
|
101
|
+
function isDocumentResult(r) {
|
|
102
|
+
return r.type === "document";
|
|
103
|
+
}
|
|
104
|
+
__name(isDocumentResult, "isDocumentResult");
|
|
105
|
+
function isCollectionResult(r) {
|
|
106
|
+
return r.type === "collection";
|
|
107
|
+
}
|
|
108
|
+
__name(isCollectionResult, "isCollectionResult");
|
|
109
|
+
function matchResult(result, handlers) {
|
|
110
|
+
switch (result.type) {
|
|
111
|
+
case "code":
|
|
112
|
+
return (handlers.code ?? handlers._)?.(result);
|
|
113
|
+
case "commit":
|
|
114
|
+
return (handlers.commit ?? handlers._)?.(result);
|
|
115
|
+
case "document":
|
|
116
|
+
return (handlers.document ?? handlers._)?.(result);
|
|
117
|
+
case "collection":
|
|
118
|
+
return (handlers.collection ?? handlers._)?.(result);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
__name(matchResult, "matchResult");
|
|
122
|
+
|
|
123
|
+
// src/providers/embeddings/embedding-worker.ts
|
|
124
|
+
import { Worker } from "worker_threads";
|
|
125
|
+
import { fileURLToPath } from "url";
|
|
126
|
+
import { join, dirname } from "path";
|
|
127
|
+
var EmbeddingWorkerProxy = class {
|
|
128
|
+
static {
|
|
129
|
+
__name(this, "EmbeddingWorkerProxy");
|
|
130
|
+
}
|
|
131
|
+
_worker;
|
|
132
|
+
_nextId = 1;
|
|
133
|
+
_pending = /* @__PURE__ */ new Map();
|
|
134
|
+
_ready;
|
|
135
|
+
_dims = 0;
|
|
136
|
+
/** Embedding dimensions (available after `ready()` resolves). */
|
|
137
|
+
get dims() {
|
|
138
|
+
return this._dims;
|
|
139
|
+
}
|
|
140
|
+
constructor(providerType, providerOptions = {}) {
|
|
141
|
+
const workerPath = join(
|
|
142
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
143
|
+
"embedding-worker-thread.ts"
|
|
144
|
+
);
|
|
145
|
+
this._worker = new Worker(workerPath, {
|
|
146
|
+
workerData: { providerType, providerOptions },
|
|
147
|
+
execArgv: ["--import", "tsx"]
|
|
148
|
+
});
|
|
149
|
+
this._worker.on("message", (msg) => {
|
|
150
|
+
if (msg.id === 0 && msg.dims) {
|
|
151
|
+
this._dims = msg.dims;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const pending = this._pending.get(msg.id);
|
|
155
|
+
if (!pending) return;
|
|
156
|
+
this._pending.delete(msg.id);
|
|
157
|
+
if (msg.type === "error") {
|
|
158
|
+
pending.reject(new Error(`BrainBank: Embedding worker error: ${msg.error}`));
|
|
159
|
+
} else {
|
|
160
|
+
pending.resolve(msg);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
this._worker.on("error", (err) => {
|
|
164
|
+
for (const pending of this._pending.values()) {
|
|
165
|
+
pending.reject(err);
|
|
166
|
+
}
|
|
167
|
+
this._pending.clear();
|
|
168
|
+
});
|
|
169
|
+
this._ready = new Promise((resolve, reject) => {
|
|
170
|
+
const onMsg = /* @__PURE__ */ __name((msg) => {
|
|
171
|
+
if (msg.id === 0 && msg.dims) {
|
|
172
|
+
this._dims = msg.dims;
|
|
173
|
+
this._worker.removeListener("message", onMsg);
|
|
174
|
+
resolve();
|
|
175
|
+
}
|
|
176
|
+
}, "onMsg");
|
|
177
|
+
this._worker.on("message", onMsg);
|
|
178
|
+
this._worker.on("error", reject);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/** Wait for the worker to be ready (provider loaded). */
|
|
182
|
+
async ready() {
|
|
183
|
+
return this._ready;
|
|
184
|
+
}
|
|
185
|
+
/** Send a request to the worker and wait for the response. */
|
|
186
|
+
_send(req) {
|
|
187
|
+
const id = this._nextId++;
|
|
188
|
+
return new Promise((resolve, reject) => {
|
|
189
|
+
this._pending.set(id, { resolve, reject });
|
|
190
|
+
this._worker.postMessage({ ...req, id });
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/** Embed a single text string. */
|
|
194
|
+
async embed(text) {
|
|
195
|
+
await this._ready;
|
|
196
|
+
const resp = await this._send({ type: "embed", text });
|
|
197
|
+
if (!resp.vector) throw new Error("BrainBank: Worker returned no vector.");
|
|
198
|
+
return new Float32Array(resp.vector);
|
|
199
|
+
}
|
|
200
|
+
/** Embed multiple texts in a batch. */
|
|
201
|
+
async embedBatch(texts) {
|
|
202
|
+
if (texts.length === 0) return [];
|
|
203
|
+
await this._ready;
|
|
204
|
+
const resp = await this._send({ type: "embedBatch", texts });
|
|
205
|
+
if (!resp.vectors) throw new Error("BrainBank: Worker returned no vectors.");
|
|
206
|
+
return resp.vectors.map((buf) => new Float32Array(buf));
|
|
207
|
+
}
|
|
208
|
+
/** Terminate the worker. */
|
|
209
|
+
async close() {
|
|
210
|
+
try {
|
|
211
|
+
await this._send({ type: "close" });
|
|
212
|
+
} catch {
|
|
213
|
+
}
|
|
214
|
+
await this._worker.terminate();
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// src/db/migrations.ts
|
|
219
|
+
function getPluginVersion(adapter, pluginName) {
|
|
220
|
+
try {
|
|
221
|
+
const row = adapter.prepare(
|
|
222
|
+
"SELECT version FROM plugin_versions WHERE plugin_name = ?"
|
|
223
|
+
).get(pluginName);
|
|
224
|
+
return row?.version ?? 0;
|
|
225
|
+
} catch {
|
|
226
|
+
return 0;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
__name(getPluginVersion, "getPluginVersion");
|
|
230
|
+
function setPluginVersion(adapter, pluginName, version) {
|
|
231
|
+
adapter.prepare(`
|
|
232
|
+
INSERT OR REPLACE INTO plugin_versions (plugin_name, version, applied_at)
|
|
233
|
+
VALUES (?, ?, unixepoch())
|
|
234
|
+
`).run(pluginName, version);
|
|
235
|
+
}
|
|
236
|
+
__name(setPluginVersion, "setPluginVersion");
|
|
237
|
+
function runPluginMigrations(adapter, pluginName, schemaVersion, migrations) {
|
|
238
|
+
const current = getPluginVersion(adapter, pluginName);
|
|
239
|
+
if (current >= schemaVersion) return;
|
|
240
|
+
const sorted = [...migrations].sort((a, b) => a.version - b.version);
|
|
241
|
+
for (const m of sorted) {
|
|
242
|
+
if (m.version <= current) continue;
|
|
243
|
+
adapter.transaction(() => {
|
|
244
|
+
m.up(adapter);
|
|
245
|
+
setPluginVersion(adapter, pluginName, m.version);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
__name(runPluginMigrations, "runPluginMigrations");
|
|
250
|
+
|
|
251
|
+
// src/search/vector/mmr.ts
|
|
252
|
+
function searchMMR(index, query, vectorCache, k, lambda = 0.7) {
|
|
253
|
+
const candidates = index.search(query, k * 3);
|
|
254
|
+
if (candidates.length <= k) return candidates;
|
|
255
|
+
const selected = [];
|
|
256
|
+
const remaining = [...candidates];
|
|
257
|
+
while (selected.length < k && remaining.length > 0) {
|
|
258
|
+
let bestScore = -Infinity;
|
|
259
|
+
let bestIdx = 0;
|
|
260
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
261
|
+
const relevance = remaining[i].score;
|
|
262
|
+
let maxSim = 0;
|
|
263
|
+
for (const sel of selected) {
|
|
264
|
+
const candidateVec = vectorCache.get(remaining[i].id);
|
|
265
|
+
const selectedVec = vectorCache.get(sel.id);
|
|
266
|
+
if (candidateVec && selectedVec) {
|
|
267
|
+
maxSim = Math.max(maxSim, cosineSimilarity(candidateVec, selectedVec));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const mmrScore = lambda * relevance - (1 - lambda) * maxSim;
|
|
271
|
+
if (mmrScore > bestScore) {
|
|
272
|
+
bestScore = mmrScore;
|
|
273
|
+
bestIdx = i;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
selected.push(remaining[bestIdx]);
|
|
277
|
+
remaining.splice(bestIdx, 1);
|
|
278
|
+
}
|
|
279
|
+
return selected;
|
|
280
|
+
}
|
|
281
|
+
__name(searchMMR, "searchMMR");
|
|
282
|
+
export {
|
|
283
|
+
BrainBank,
|
|
284
|
+
Collection,
|
|
285
|
+
CompositeBM25Search,
|
|
286
|
+
CompositeVectorSearch,
|
|
287
|
+
ContextBuilder,
|
|
288
|
+
DEFAULTS,
|
|
289
|
+
DEFAULT_PORT,
|
|
290
|
+
EmbeddingWorkerProxy,
|
|
291
|
+
HNSW,
|
|
292
|
+
HNSWIndex,
|
|
293
|
+
HaikuExpander,
|
|
294
|
+
HaikuPruner,
|
|
295
|
+
HttpServer,
|
|
296
|
+
IGNORE_DIRS,
|
|
297
|
+
KVService,
|
|
298
|
+
LocalEmbedding,
|
|
299
|
+
OpenAIEmbedding,
|
|
300
|
+
PerplexityContextEmbedding,
|
|
301
|
+
PerplexityEmbedding,
|
|
302
|
+
SQLiteAdapter,
|
|
303
|
+
SUPPORTED_EXTENSIONS,
|
|
304
|
+
Watcher,
|
|
305
|
+
WebhookServer,
|
|
306
|
+
acquireLock,
|
|
307
|
+
bumpVersion,
|
|
308
|
+
contextFromCLI,
|
|
309
|
+
cosineSimilarity,
|
|
310
|
+
createBrain,
|
|
311
|
+
createTracker,
|
|
312
|
+
escapeLike,
|
|
313
|
+
getLanguage,
|
|
314
|
+
getServerUrl,
|
|
315
|
+
getVersion,
|
|
316
|
+
getVersions,
|
|
317
|
+
isBM25SearchPlugin,
|
|
318
|
+
isCoEditPlugin,
|
|
319
|
+
isCodeResult,
|
|
320
|
+
isCollectionResult,
|
|
321
|
+
isCommitResult,
|
|
322
|
+
isContextFieldPlugin,
|
|
323
|
+
isContextFormatterPlugin,
|
|
324
|
+
isDocsPlugin,
|
|
325
|
+
isDocumentResult,
|
|
326
|
+
isExpandablePlugin,
|
|
327
|
+
isFileResolvable,
|
|
328
|
+
isIgnoredDir,
|
|
329
|
+
isIgnoredFile,
|
|
330
|
+
isIndexable,
|
|
331
|
+
isMigratable,
|
|
332
|
+
isReembeddable,
|
|
333
|
+
isSearchable,
|
|
334
|
+
isServerRunning,
|
|
335
|
+
isSupported,
|
|
336
|
+
isVectorSearchPlugin,
|
|
337
|
+
isWatchable,
|
|
338
|
+
matchResult,
|
|
339
|
+
normalize,
|
|
340
|
+
normalizeBM25,
|
|
341
|
+
providerKey,
|
|
342
|
+
pruneResults,
|
|
343
|
+
readPid,
|
|
344
|
+
reciprocalRankFusion,
|
|
345
|
+
releaseLock,
|
|
346
|
+
removePid,
|
|
347
|
+
resetFactoryCache,
|
|
348
|
+
resolveConfig,
|
|
349
|
+
resolveEmbedding,
|
|
350
|
+
runPluginMigrations,
|
|
351
|
+
sanitizeFTS,
|
|
352
|
+
searchMMR,
|
|
353
|
+
vecToBuffer,
|
|
354
|
+
withLock,
|
|
355
|
+
writePid
|
|
356
|
+
};
|
|
357
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/providers/embeddings/embedding-worker.ts","../src/db/migrations.ts","../src/search/vector/mmr.ts"],"sourcesContent":["/**\n * BrainBank — Type Definitions\n * \n * All interfaces and types for the semantic knowledge bank.\n */\n\n\nimport type { CollectionItem, CollectionSearchOptions, CollectionAddOptions } from './services/collection.ts';\n\n// Re-export collection types so consumers don't need to import from services/\nexport type { CollectionItem, CollectionSearchOptions, CollectionAddOptions };\n\n\n/** Public contract for a KV collection. Plugins depend on this interface, not the concrete class. */\nexport interface ICollection {\n /** Collection name. */\n readonly name: string;\n /** Add an item. Returns its ID. */\n add(content: string, options?: CollectionAddOptions | Record<string, unknown>): Promise<number>;\n /** Update an item's content (re-embeds). Returns the new ID. */\n update(id: number, content: string, options?: CollectionAddOptions): Promise<number>;\n /** Add multiple items. Returns their IDs. */\n addMany(items: { content: string; metadata?: Record<string, unknown>; tags?: string[]; ttl?: string }[]): Promise<number[]>;\n /** Search this collection. */\n search(query: string, options?: CollectionSearchOptions): Promise<CollectionItem[]>;\n /** List items (newest first). */\n list(options?: { limit?: number; offset?: number; tags?: string[] }): CollectionItem[];\n /** Count items in this collection. */\n count(): number;\n /** Keep only the N most recent items. */\n trim(options: { keep: number }): Promise<{ removed: number }>;\n /** Remove items older than a duration string. */\n prune(options: { olderThan: string }): Promise<{ removed: number }>;\n /** Remove a specific item by ID. */\n remove(id: number): void;\n /** Clear all items in this collection. */\n clear(): void;\n}\n\n\nexport interface BrainBankConfig {\n /** Root path of the repository to index. Default: '.' */\n repoPath?: string;\n /** SQLite database path. Default: '.brainbank/data/brainbank.db' */\n dbPath?: string;\n\n /** Max git commits to index. Default: 500 */\n gitDepth?: number;\n /** Max file size in bytes to index. Default: 512_000 (500KB) */\n maxFileSize?: number;\n /** Max diff bytes per commit. Default: 8192 */\n maxDiffBytes?: number;\n /** HNSW M parameter (connections per node). Default: 16 */\n hnswM?: number;\n /** HNSW efConstruction (build-time candidates). Default: 200 */\n hnswEfConstruction?: number;\n /** HNSW efSearch (query-time candidates). Default: 50 */\n hnswEfSearch?: number;\n /** Embedding dimensions. Default: 384 */\n embeddingDims?: number;\n /** Max HNSW elements. Default: 2_000_000 */\n maxElements?: number;\n /** Custom embedding provider (default: local WASM model) */\n embeddingProvider?: EmbeddingProvider;\n /** Optional LLM noise filter — drops irrelevant results before formatting */\n pruner?: Pruner;\n /** Optional LLM context expander — discovers additional relevant chunks after pruning */\n expander?: Expander;\n /** Port for optional webhook server (enables push-based watch plugins). */\n webhookPort?: number;\n /** Context field defaults from config.json \"context\" section. */\n contextFields?: Record<string, unknown>;\n}\n\nexport interface ResolvedConfig {\n repoPath: string;\n dbPath: string;\n gitDepth: number;\n maxFileSize: number;\n maxDiffBytes: number;\n hnswM: number;\n hnswEfConstruction: number;\n hnswEfSearch: number;\n embeddingDims: number;\n maxElements: number;\n embeddingProvider?: EmbeddingProvider;\n pruner?: Pruner;\n expander?: Expander;\n webhookPort?: number;\n /** Context field defaults from config.json \"context\" section. */\n contextFields?: Record<string, unknown>;\n}\n\n\nexport interface EmbeddingProvider {\n /** Vector dimensions produced by this provider. */\n readonly dims: number;\n /** Embed a single text string. */\n embed(text: string): Promise<Float32Array>;\n /** Embed multiple texts (batch). */\n embedBatch(texts: string[]): Promise<Float32Array[]>;\n /** Release resources. */\n close(): Promise<void>;\n}\n\n\n\n/** Item passed to the pruner for noise classification. */\nexport interface PrunerItem {\n /** Positional index (used to map back to SearchResult[]) */\n id: number;\n /** File path — primary signal for relevance */\n filePath: string;\n /** Trimmed content preview */\n preview: string;\n /** Chunk metadata (type, name, language, lines, etc.) */\n metadata: Record<string, unknown>;\n}\n\nexport interface Pruner {\n /**\n * Filter noise from search results and order by semantic relevance.\n * @param query - The search query\n * @param items - Items to evaluate (filePath + metadata + trimmed preview)\n * @returns Array of item IDs to KEEP, ordered by relevance to the query\n * (most relevant first). Everything else is dropped.\n */\n prune(query: string, items: PrunerItem[]): Promise<number[]>;\n /** Release resources. */\n close?(): Promise<void>;\n}\n\n/** Lightweight chunk descriptor for the expander manifest. */\nexport interface ExpanderManifestItem {\n /** Chunk ID (code_chunks.id) */\n id: number;\n /** File path */\n filePath: string;\n /** Chunk name (e.g. function/class name) */\n name: string;\n /** Chunk type (function, class, method, etc.) */\n chunkType: string;\n /** Line range (e.g. \"L45-L89\") */\n lines: string;\n /** True if this chunk is from an import-graph neighbor of the search results. */\n priority?: boolean;\n}\n\n/** Result from the expander: chunk IDs to add + optional free-text note. */\nexport interface ExpanderResult {\n /** Additional chunk IDs to splice into results. */\n ids: number[];\n /** Brief observation for the agent (e.g. \"file X not found\", \"module Y is deprecated\"). */\n note?: string;\n}\n\nexport interface Expander {\n /**\n * Given a task and a manifest of available chunks,\n * return additional chunk IDs + an optional contextual note.\n * Runs after pruning. Fail-open: errors return empty result.\n *\n * @param query - The search query / task description\n * @param currentIds - IDs of chunks already in results (from search + prune)\n * @param manifest - All available chunks (lightweight descriptors)\n * @returns Chunk IDs to add + optional note\n */\n expand(query: string, currentIds: number[], manifest: ExpanderManifestItem[]): Promise<ExpanderResult>;\n /** Release resources. */\n close?(): Promise<void>;\n}\n\n\nexport interface SearchHit {\n id: number;\n score: number;\n}\n\nexport interface VectorIndex {\n /** Initialize the index. Must be called before add/search. */\n init(): Promise<this>;\n /** Add a vector with an integer ID. Idempotent: duplicate IDs are skipped. */\n add(vector: Float32Array, id: number): void;\n /** Mark a vector as deleted so it no longer appears in searches. */\n remove(id: number): void;\n /** Search for k nearest neighbors. */\n search(query: Float32Array, k: number): SearchHit[];\n /** Clear all vectors and reset to empty state. */\n reinit(): void;\n /** Number of vectors in the index. */\n readonly size: number;\n}\n\n\nexport interface CodeChunk {\n /** Auto-incremented DB id (set after insert) */\n id?: number;\n /** Relative file path from repo root */\n filePath: string;\n /** Chunk type: 'file' | 'function' | 'class' | 'block' */\n chunkType: string;\n /** Function/class name (if detected) */\n name?: string;\n /** Start line (1-indexed) */\n startLine: number;\n /** End line (1-indexed, inclusive) */\n endLine: number;\n /** Raw content of the chunk */\n content: string;\n /** Language identifier */\n language: string;\n}\n\n\nexport interface GitCommitRecord {\n id?: number;\n hash: string;\n shortHash: string;\n message: string;\n author: string;\n date: string;\n timestamp: number;\n filesChanged: string[];\n diff?: string;\n additions: number;\n deletions: number;\n isMerge: boolean;\n}\n\n\n\n\n\nexport type SearchResultType = 'code' | 'commit' | 'document' | 'collection';\n\n// Typed metadata per result type\n\nexport interface CodeResultMetadata {\n /** Database chunk ID (used by call graph annotations). */\n id?: number;\n /** File path (may duplicate CodeResult.filePath for metadata-only access). */\n filePath?: string;\n /** Adjacent chunk IDs from the same file (used by context expansion). */\n chunkIds?: number[];\n chunkType: string;\n name?: string;\n startLine: number;\n endLine: number;\n language: string;\n searchType?: string;\n rrfScore?: number;\n}\n\nexport interface CommitResultMetadata {\n hash: string;\n shortHash: string;\n author: string;\n date: string;\n files: string[];\n additions?: number;\n deletions?: number;\n diff?: string;\n searchType?: string;\n rrfScore?: number;\n}\n\n\n\nexport interface DocumentResultMetadata {\n collection?: string;\n title?: string;\n seq?: number;\n path?: string;\n searchType?: string;\n /** Internal chunk ID used by hybrid search to map fused results. */\n chunkId?: number;\n rrfScore?: number;\n}\n\n// Discriminated union\n\nexport interface CodeResult {\n type: 'code';\n score: number;\n filePath: string;\n content: string;\n context?: string;\n metadata: CodeResultMetadata;\n}\n\nexport interface CommitResult {\n type: 'commit';\n score: number;\n filePath?: string;\n content: string;\n context?: string;\n metadata: CommitResultMetadata;\n}\n\n\n\nexport interface DocumentResult {\n type: 'document';\n score: number;\n filePath: string;\n content: string;\n context?: string;\n metadata: DocumentResultMetadata;\n}\n\nexport interface CollectionResultMetadata {\n id?: number;\n collection?: string;\n rrfScore?: number;\n [key: string]: unknown;\n}\n\nexport interface CollectionResult {\n type: 'collection';\n score: number;\n filePath?: string;\n content: string;\n context?: string;\n metadata: CollectionResultMetadata;\n}\n\nexport type SearchResult = CodeResult | CommitResult | DocumentResult | CollectionResult;\n\n\n/** Narrow a SearchResult to CodeResult. */\nexport function isCodeResult(r: SearchResult): r is CodeResult {\n return r.type === 'code';\n}\n/** Narrow a SearchResult to CommitResult. */\nexport function isCommitResult(r: SearchResult): r is CommitResult {\n return r.type === 'commit';\n}\n/** Narrow a SearchResult to DocumentResult. */\nexport function isDocumentResult(r: SearchResult): r is DocumentResult {\n return r.type === 'document';\n}\n\n/** Narrow a SearchResult to CollectionResult. */\nexport function isCollectionResult(r: SearchResult): r is CollectionResult {\n return r.type === 'collection';\n}\n\n\ntype MatchHandlers<T> = {\n code?: (r: CodeResult) => T;\n commit?: (r: CommitResult) => T;\n document?: (r: DocumentResult) => T;\n collection?: (r: CollectionResult) => T;\n _?: (r: SearchResult) => T;\n};\n\n/**\n * Pattern-match on SearchResult type. Calls the matching handler\n * or the `_` fallback. Returns undefined if no handler matches.\n */\nexport function matchResult<T>(\n result: SearchResult,\n handlers: MatchHandlers<T>,\n): T | undefined {\n switch (result.type) {\n case 'code': return (handlers.code ?? handlers._)?.(result);\n case 'commit': return (handlers.commit ?? handlers._)?.(result);\n case 'document': return (handlers.document ?? handlers._)?.(result);\n case 'collection': return (handlers.collection ?? handlers._)?.(result);\n }\n}\n\n\nexport interface ContextOptions {\n /** Per-source result limits. Built-in: 'code', 'git'. Default: { code: 6, git: 5 } */\n sources?: Record<string, number>;\n /** Files the agent is about to modify (improves co-edit suggestions) */\n affectedFiles?: string[];\n /** Minimum similarity score threshold. Default: 0.25 */\n minScore?: number;\n /** Use MMR for diversity. Default: true */\n useMMR?: boolean;\n /** MMR lambda (0 = diversity, 1 = relevance). Default: 0.7 */\n mmrLambda?: number;\n /** Filter results to files under these path prefixes (e.g. 'src/services/' or ['src/', 'lib/']). */\n pathPrefix?: string | string[];\n /** Exclude results whose filePath starts with any of these prefixes (e.g. ['src/tests/', 'src/mocks/']). */\n ignorePaths?: string[];\n /** File paths to exclude from results (e.g. files already returned in a previous query). */\n excludeFiles?: Set<string>;\n /** Optional per-request pruner override (e.g. HaikuPruner for LLM noise filtering). */\n pruner?: Pruner;\n /** Caller origin for debug logging. */\n source?: 'cli' | 'mcp' | 'daemon' | 'api';\n /**\n * Context field overrides. Merged on top of config.json \"context\" defaults.\n * Plugin-defined fields like `lines`, `callTree`, `symbols`, `compact`, `imports`.\n * Example: `{ lines: true, callTree: { depth: 3 }, symbols: true }`\n */\n fields?: Record<string, unknown>;\n}\n\n\nexport interface DocumentCollection {\n /** Collection name (e.g. 'notes', 'docs') */\n name: string;\n /** Directory path to index */\n path: string;\n /** Glob pattern for files (default: all markdown) */\n pattern?: string;\n /** Glob patterns to ignore */\n ignore?: string[];\n /** Context description for this collection */\n context?: string;\n}\n\nexport interface DocChunk {\n id?: number;\n /** Collection name */\n collection: string;\n /** Relative file path within the collection */\n filePath: string;\n /** Document title (first heading or filename) */\n title: string;\n /** Chunk content */\n content: string;\n /** Chunk sequence within the document (0, 1, 2...) */\n seq: number;\n /** Character position in original document */\n pos: number;\n /** Content hash for incremental updates */\n contentHash: string;\n}\n\n\n/** Plugin-provided stats. Key is the plugin name. */\nexport interface IndexStats {\n [pluginName: string]: Record<string, number | string> | undefined;\n}\n\n\n/** File-level progress (used by indexers). */\nexport type ProgressCallback = (file: string, current: number, total: number) => void;\n\n/** Stage-level progress (used by BrainBank.index() orchestrator). */\nexport type StageProgressCallback = (stage: string, message: string) => void;\n\nexport interface IndexResult {\n indexed: number;\n skipped: number;\n chunks?: number;\n removed?: number;\n}\n\n\nexport interface CoEditSuggestion {\n file: string;\n count: number;\n}\n\n\n/** Generalized watch event — works for files, APIs, webhooks. */\nexport interface WatchEvent {\n /** Event type. 'sync' is for batch/poll sources that don't distinguish CRUD. */\n type: 'create' | 'update' | 'delete' | 'sync';\n /** Unique ID of the changed item (file path, PR#123, PROJ-456, etc.). */\n sourceId: string;\n /** Source descriptor (e.g. 'file', 'github:pr', 'jira:card'). */\n sourceName: string;\n /** Optional raw payload to avoid re-fetching. */\n payload?: unknown;\n}\n\n/** Callback that plugins invoke when they detect a change. */\nexport type WatchEventHandler = (event: WatchEvent) => void;\n\n/** Lifecycle handle returned by WatchablePlugin.watch(). */\nexport interface WatchHandle {\n /** Stop watching and release resources. */\n stop(): Promise<void>;\n /** Whether the watcher is still active. */\n readonly active: boolean;\n}\n\n/** Optional hints from plugin to core — debounce, batching, priority. */\nexport interface WatchConfig {\n /** Debounce interval in ms. 0 = process immediately. Default: inherited from WatchOptions. */\n debounceMs?: number;\n /** Max events to batch before triggering re-index. Default: unlimited. */\n batchSize?: number;\n /** Processing priority. Default: 'realtime'. */\n priority?: 'realtime' | 'background';\n}\n","/**\n * BrainBank — Embedding Worker Proxy\n *\n * Drop-in replacement for any EmbeddingProvider that offloads\n * embedding computation to a dedicated worker thread.\n * The main thread's event loop stays free for serving searches.\n *\n * Usage:\n * const proxy = new EmbeddingWorkerProxy('local', { model: '...' });\n * await proxy.ready();\n * const vec = await proxy.embed('hello');\n */\n\nimport type { EmbeddingProvider } from '@/types.ts';\n\nimport { Worker } from 'node:worker_threads';\nimport { fileURLToPath } from 'node:url';\nimport { join, dirname } from 'node:path';\n\n/** Message sent to the worker. */\ninterface WorkerRequest {\n id: number;\n type: 'embed' | 'embedBatch' | 'close';\n text?: string;\n texts?: string[];\n}\n\n/** Message received from the worker. */\ninterface WorkerResponse {\n id: number;\n type: 'result' | 'error';\n vector?: ArrayBuffer;\n vectors?: ArrayBuffer[];\n dims?: number;\n error?: string;\n}\n\nexport class EmbeddingWorkerProxy implements EmbeddingProvider {\n private _worker: Worker;\n private _nextId = 1;\n private _pending = new Map<number, { resolve: (v: WorkerResponse) => void; reject: (e: Error) => void }>();\n private _ready: Promise<void>;\n private _dims = 0;\n\n /** Embedding dimensions (available after `ready()` resolves). */\n get dims(): number { return this._dims; }\n\n constructor(\n providerType: string,\n providerOptions: Record<string, unknown> = {},\n ) {\n const workerPath = join(\n dirname(fileURLToPath(import.meta.url)),\n 'embedding-worker-thread.ts',\n );\n\n this._worker = new Worker(workerPath, {\n workerData: { providerType, providerOptions },\n execArgv: ['--import', 'tsx'],\n });\n\n this._worker.on('message', (msg: WorkerResponse) => {\n // Initial ready signal (id === 0)\n if (msg.id === 0 && msg.dims) {\n this._dims = msg.dims;\n return;\n }\n\n const pending = this._pending.get(msg.id);\n if (!pending) return;\n this._pending.delete(msg.id);\n\n if (msg.type === 'error') {\n pending.reject(new Error(`BrainBank: Embedding worker error: ${msg.error}`));\n } else {\n pending.resolve(msg);\n }\n });\n\n this._worker.on('error', (err: Error) => {\n for (const pending of this._pending.values()) {\n pending.reject(err);\n }\n this._pending.clear();\n });\n\n // Wait for the worker to signal ready\n this._ready = new Promise<void>((resolve, reject) => {\n const onMsg = (msg: WorkerResponse) => {\n if (msg.id === 0 && msg.dims) {\n this._dims = msg.dims;\n this._worker.removeListener('message', onMsg);\n resolve();\n }\n };\n this._worker.on('message', onMsg);\n this._worker.on('error', reject);\n });\n }\n\n /** Wait for the worker to be ready (provider loaded). */\n async ready(): Promise<void> {\n return this._ready;\n }\n\n /** Send a request to the worker and wait for the response. */\n private _send(req: Omit<WorkerRequest, 'id'>): Promise<WorkerResponse> {\n const id = this._nextId++;\n return new Promise<WorkerResponse>((resolve, reject) => {\n this._pending.set(id, { resolve, reject });\n this._worker.postMessage({ ...req, id } satisfies WorkerRequest);\n });\n }\n\n /** Embed a single text string. */\n async embed(text: string): Promise<Float32Array> {\n await this._ready;\n const resp = await this._send({ type: 'embed', text });\n if (!resp.vector) throw new Error('BrainBank: Worker returned no vector.');\n return new Float32Array(resp.vector);\n }\n\n /** Embed multiple texts in a batch. */\n async embedBatch(texts: string[]): Promise<Float32Array[]> {\n if (texts.length === 0) return [];\n await this._ready;\n const resp = await this._send({ type: 'embedBatch', texts });\n if (!resp.vectors) throw new Error('BrainBank: Worker returned no vectors.');\n return resp.vectors.map(buf => new Float32Array(buf));\n }\n\n /** Terminate the worker. */\n async close(): Promise<void> {\n try {\n await this._send({ type: 'close' });\n } catch {\n // Worker may already be terminated\n }\n await this._worker.terminate();\n }\n}\n","/**\n * BrainBank — Plugin Migration System\n *\n * Per-plugin versioned schema migrations.\n * Each plugin declares a schemaVersion + ordered migrations array.\n * Core stores applied versions in `plugin_versions` table.\n *\n * Plugins call `runPluginMigrations()` at the top of their `initialize()`.\n * Migrations use `IF NOT EXISTS` so first run on an existing DB is a no-op.\n */\n\nimport type { DatabaseAdapter } from './adapter.ts';\n\n/** A single migration step. */\nexport interface Migration {\n /** Version this migration brings the schema to. */\n version: number;\n /** Apply the migration. Must be idempotent (use IF NOT EXISTS). */\n up(adapter: DatabaseAdapter): void;\n}\n\n/** Get the currently stored schema version for a plugin. Returns 0 if no record. */\nexport function getPluginVersion(adapter: DatabaseAdapter, pluginName: string): number {\n try {\n const row = adapter.prepare(\n 'SELECT version FROM plugin_versions WHERE plugin_name = ?'\n ).get(pluginName) as { version: number } | undefined;\n return row?.version ?? 0;\n } catch {\n return 0;\n }\n}\n\n/** Set the schema version for a plugin. */\nexport function setPluginVersion(adapter: DatabaseAdapter, pluginName: string, version: number): void {\n adapter.prepare(`\n INSERT OR REPLACE INTO plugin_versions (plugin_name, version, applied_at)\n VALUES (?, ?, unixepoch())\n `).run(pluginName, version);\n}\n\n/**\n * Run pending migrations for a plugin.\n * Skips migrations whose version <= stored version.\n * Each migration runs in its own transaction.\n */\nexport function runPluginMigrations(\n adapter: DatabaseAdapter,\n pluginName: string,\n schemaVersion: number,\n migrations: Migration[],\n): void {\n const current = getPluginVersion(adapter, pluginName);\n if (current >= schemaVersion) return;\n\n const sorted = [...migrations].sort((a, b) => a.version - b.version);\n\n for (const m of sorted) {\n if (m.version <= current) continue;\n\n adapter.transaction(() => {\n m.up(adapter);\n setPluginVersion(adapter, pluginName, m.version);\n });\n }\n}\n","/**\n * BrainBank — Maximum Marginal Relevance (MMR)\n * \n * Diversifies vector search results to avoid returning redundant items.\n * λ=1.0 → pure relevance, λ=0.0 → pure diversity.\n * Default λ=0.7 balances both.\n */\n\nimport type { VectorIndex, SearchHit } from '@/types.ts';\nimport { cosineSimilarity } from '@/lib/math.ts';\n\n/**\n * Search with Maximum Marginal Relevance for diversified results.\n * \n * Algorithm:\n * 1. Get 3x candidates from HNSW\n * 2. Greedily select items that maximize: λ * relevance - (1-λ) * max_sim_to_selected\n */\nexport function searchMMR(\n index: VectorIndex,\n query: Float32Array,\n vectorCache: Map<number, Float32Array>,\n k: number,\n lambda: number = 0.7,\n): SearchHit[] {\n // Get more candidates than needed\n const candidates = index.search(query, k * 3);\n if (candidates.length <= k) return candidates;\n\n const selected: SearchHit[] = [];\n const remaining = [...candidates];\n\n while (selected.length < k && remaining.length > 0) {\n let bestScore = -Infinity;\n let bestIdx = 0;\n\n for (let i = 0; i < remaining.length; i++) {\n const relevance = remaining[i].score;\n\n // Max similarity to any already-selected item\n let maxSim = 0;\n for (const sel of selected) {\n const candidateVec = vectorCache.get(remaining[i].id);\n const selectedVec = vectorCache.get(sel.id);\n if (candidateVec && selectedVec) {\n maxSim = Math.max(maxSim, cosineSimilarity(candidateVec, selectedVec));\n }\n }\n\n // MMR score: balance relevance vs diversity\n const mmrScore = lambda * relevance - (1 - lambda) * maxSim;\n\n if (mmrScore > bestScore) {\n bestScore = mmrScore;\n bestIdx = i;\n }\n }\n\n selected.push(remaining[bestIdx]);\n remaining.splice(bestIdx, 1);\n }\n\n return selected;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/mcp.d.ts
ADDED