@neuralsea/workspace-indexer 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/browser/index.js +442 -0
- package/dist/{chunk-TQTWTPPG.js → chunk-7B5W6SSN.js} +101 -43
- package/dist/cli.cjs +100 -39
- package/dist/cli.js +1 -1
- package/dist/index.cjs +145 -84
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +14 -3
package/README.md
CHANGED
|
@@ -33,6 +33,18 @@ npm i @neuralsea/workspace-indexer
|
|
|
33
33
|
|
|
34
34
|
Node 18+ required.
|
|
35
35
|
|
|
36
|
+
Docs: `docs/README.md`
|
|
37
|
+
|
|
38
|
+
### Browser / VS Code webview
|
|
39
|
+
|
|
40
|
+
This package publishes a browser-safe entrypoint for use in browsers and VS Code webviews:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { chunkSource, OpenAIEmbeddingsProvider } from "@neuralsea/workspace-indexer/browser";
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The full indexer (`WorkspaceIndexer`, file watching, git scanning, sqlite-on-disk, etc.) is Node-only and should run in the VS Code extension host (send data to the webview via `postMessage`).
|
|
47
|
+
|
|
36
48
|
---
|
|
37
49
|
|
|
38
50
|
## Quick start (library)
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
// src/embeddings/openai.ts
|
|
2
|
+
var OpenAIEmbeddingsProvider = class {
|
|
3
|
+
constructor(opts) {
|
|
4
|
+
this.opts = opts;
|
|
5
|
+
this.id = `openai:${opts.model}`;
|
|
6
|
+
}
|
|
7
|
+
id;
|
|
8
|
+
dimension = null;
|
|
9
|
+
async embed(texts) {
|
|
10
|
+
const baseUrl = this.opts.baseUrl ?? "https://api.openai.com";
|
|
11
|
+
const res = await fetch(`${baseUrl}/v1/embeddings`, {
|
|
12
|
+
method: "POST",
|
|
13
|
+
headers: {
|
|
14
|
+
"Authorization": `Bearer ${this.opts.apiKey}`,
|
|
15
|
+
"Content-Type": "application/json"
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify({
|
|
18
|
+
model: this.opts.model,
|
|
19
|
+
input: texts
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
if (!res.ok) {
|
|
23
|
+
const errText = await res.text().catch(() => "");
|
|
24
|
+
throw new Error(`OpenAI embeddings failed: ${res.status} ${res.statusText} ${errText}`);
|
|
25
|
+
}
|
|
26
|
+
const json = await res.json();
|
|
27
|
+
const arr = json.data.map((d) => Float32Array.from(d.embedding));
|
|
28
|
+
if (arr.length > 0) this.dimension = arr[0].length;
|
|
29
|
+
return arr;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/embeddings/ollama.ts
|
|
34
|
+
import pLimit from "p-limit";
|
|
35
|
+
var OllamaEmbeddingsProvider = class {
|
|
36
|
+
id;
|
|
37
|
+
dimension = null;
|
|
38
|
+
baseUrl;
|
|
39
|
+
model;
|
|
40
|
+
concurrency;
|
|
41
|
+
constructor(opts) {
|
|
42
|
+
this.model = opts.model;
|
|
43
|
+
this.baseUrl = opts.baseUrl ?? "http://localhost:11434";
|
|
44
|
+
this.concurrency = opts.concurrency ?? 4;
|
|
45
|
+
this.id = `ollama:${this.model}`;
|
|
46
|
+
}
|
|
47
|
+
async tryBatchEndpoint(texts) {
|
|
48
|
+
const res = await fetch(`${this.baseUrl}/api/embed`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: { "Content-Type": "application/json" },
|
|
51
|
+
body: JSON.stringify({ model: this.model, input: texts })
|
|
52
|
+
}).catch(() => null);
|
|
53
|
+
if (!res || !res.ok) return null;
|
|
54
|
+
const json = await res.json();
|
|
55
|
+
const embeddings = json.embeddings;
|
|
56
|
+
if (!embeddings) return null;
|
|
57
|
+
const out = embeddings.map((v) => Float32Array.from(v));
|
|
58
|
+
if (out.length > 0) this.dimension = out[0].length;
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
async embedOne(text) {
|
|
62
|
+
const res = await fetch(`${this.baseUrl}/api/embeddings`, {
|
|
63
|
+
method: "POST",
|
|
64
|
+
headers: { "Content-Type": "application/json" },
|
|
65
|
+
body: JSON.stringify({ model: this.model, prompt: text })
|
|
66
|
+
});
|
|
67
|
+
if (!res.ok) {
|
|
68
|
+
const errText = await res.text().catch(() => "");
|
|
69
|
+
throw new Error(`Ollama embeddings failed: ${res.status} ${res.statusText} ${errText}`);
|
|
70
|
+
}
|
|
71
|
+
const json = await res.json();
|
|
72
|
+
const emb = Float32Array.from(json.embedding);
|
|
73
|
+
this.dimension = emb.length;
|
|
74
|
+
return emb;
|
|
75
|
+
}
|
|
76
|
+
async embed(texts) {
|
|
77
|
+
const batch = await this.tryBatchEndpoint(texts);
|
|
78
|
+
if (batch) return batch;
|
|
79
|
+
const limit = pLimit(this.concurrency);
|
|
80
|
+
const out = await Promise.all(texts.map((t) => limit(() => this.embedOne(t))));
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/embeddings/hash.ts
|
|
86
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
87
|
+
var HashEmbeddingsProvider = class {
|
|
88
|
+
id;
|
|
89
|
+
dimension;
|
|
90
|
+
constructor(dimension = 384) {
|
|
91
|
+
this.dimension = dimension;
|
|
92
|
+
this.id = `hash:${dimension}`;
|
|
93
|
+
}
|
|
94
|
+
async embed(texts) {
|
|
95
|
+
return texts.map((t) => this.embedOne(t));
|
|
96
|
+
}
|
|
97
|
+
embedOne(text) {
|
|
98
|
+
const v = new Float32Array(this.dimension);
|
|
99
|
+
const tokens = text.split(/[^A-Za-z0-9_]+/).filter(Boolean).slice(0, 6e3);
|
|
100
|
+
for (const tok of tokens) {
|
|
101
|
+
const h = sha256(new TextEncoder().encode(tok));
|
|
102
|
+
const u32 = ((h[0] ?? 0) | (h[1] ?? 0) << 8 | (h[2] ?? 0) << 16 | (h[3] ?? 0) << 24) >>> 0;
|
|
103
|
+
const idx = u32 % this.dimension;
|
|
104
|
+
const sign = (h[4] ?? 0) & 1 ? 1 : -1;
|
|
105
|
+
v[idx] += sign;
|
|
106
|
+
}
|
|
107
|
+
let sumSq = 0;
|
|
108
|
+
for (let i = 0; i < v.length; i++) sumSq += v[i] * v[i];
|
|
109
|
+
const norm = Math.sqrt(sumSq) || 1;
|
|
110
|
+
for (let i = 0; i < v.length; i++) v[i] /= norm;
|
|
111
|
+
return v;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// src/profiles.ts
|
|
116
|
+
var DEFAULT_PROFILES = {
|
|
117
|
+
search: {
|
|
118
|
+
name: "search",
|
|
119
|
+
k: 10,
|
|
120
|
+
weights: { vector: 0.65, lexical: 0.35, recency: 0 },
|
|
121
|
+
expand: { adjacentChunks: 0, followImports: 0, includeFileSynopsis: false },
|
|
122
|
+
candidates: { vectorK: 25, lexicalK: 25, maxMergedCandidates: 60 }
|
|
123
|
+
},
|
|
124
|
+
refactor: {
|
|
125
|
+
name: "refactor",
|
|
126
|
+
k: 15,
|
|
127
|
+
weights: { vector: 0.55, lexical: 0.35, recency: 0.1 },
|
|
128
|
+
expand: { adjacentChunks: 1, followImports: 2, includeFileSynopsis: true },
|
|
129
|
+
candidates: { vectorK: 60, lexicalK: 40, maxMergedCandidates: 140 }
|
|
130
|
+
},
|
|
131
|
+
review: {
|
|
132
|
+
name: "review",
|
|
133
|
+
k: 20,
|
|
134
|
+
weights: { vector: 0.45, lexical: 0.35, recency: 0.2 },
|
|
135
|
+
expand: { adjacentChunks: 1, followImports: 1, includeFileSynopsis: true },
|
|
136
|
+
candidates: { vectorK: 80, lexicalK: 60, maxMergedCandidates: 180 }
|
|
137
|
+
},
|
|
138
|
+
architecture: {
|
|
139
|
+
name: "architecture",
|
|
140
|
+
k: 20,
|
|
141
|
+
weights: { vector: 0.7, lexical: 0.2, recency: 0.1 },
|
|
142
|
+
expand: { adjacentChunks: 0, followImports: 3, includeFileSynopsis: true },
|
|
143
|
+
candidates: { vectorK: 120, lexicalK: 40, maxMergedCandidates: 220 }
|
|
144
|
+
},
|
|
145
|
+
rca: {
|
|
146
|
+
name: "rca",
|
|
147
|
+
k: 25,
|
|
148
|
+
weights: { vector: 0.5, lexical: 0.25, recency: 0.25 },
|
|
149
|
+
expand: { adjacentChunks: 2, followImports: 1, includeFileSynopsis: true },
|
|
150
|
+
candidates: { vectorK: 140, lexicalK: 80, maxMergedCandidates: 260 }
|
|
151
|
+
},
|
|
152
|
+
custom: {
|
|
153
|
+
name: "custom",
|
|
154
|
+
k: 10,
|
|
155
|
+
weights: { vector: 0.65, lexical: 0.35, recency: 0 },
|
|
156
|
+
expand: { adjacentChunks: 0, followImports: 0, includeFileSynopsis: false },
|
|
157
|
+
candidates: { vectorK: 25, lexicalK: 25, maxMergedCandidates: 60 }
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
function deepMergeProfile(base, patch) {
|
|
161
|
+
if (!patch) return base;
|
|
162
|
+
const merged = {
|
|
163
|
+
...base,
|
|
164
|
+
...patch,
|
|
165
|
+
weights: { ...base.weights, ...patch.weights ?? {} },
|
|
166
|
+
expand: { ...base.expand, ...patch.expand ?? {} },
|
|
167
|
+
candidates: { ...base.candidates, ...patch.candidates ?? {} }
|
|
168
|
+
};
|
|
169
|
+
return merged;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/util.ts
|
|
173
|
+
import { sha256 as sha2562 } from "@noble/hashes/sha256";
|
|
174
|
+
import { bytesToHex } from "@noble/hashes/utils";
|
|
175
|
+
function toBytes(data) {
|
|
176
|
+
return typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
177
|
+
}
|
|
178
|
+
function sha256Hex(data) {
|
|
179
|
+
return bytesToHex(sha2562(toBytes(data)));
|
|
180
|
+
}
|
|
181
|
+
function toPosixPath(p) {
|
|
182
|
+
return p.replace(/\\/g, "/");
|
|
183
|
+
}
|
|
184
|
+
function fromPosixPath(p) {
|
|
185
|
+
if (typeof process !== "undefined" && process.platform === "win32") return p.replace(/\//g, "\\");
|
|
186
|
+
return p;
|
|
187
|
+
}
|
|
188
|
+
function estimateTokens(text) {
|
|
189
|
+
return Math.max(1, Math.ceil(text.length / 4));
|
|
190
|
+
}
|
|
191
|
+
function normalise(vec) {
|
|
192
|
+
let sumSq = 0;
|
|
193
|
+
for (let i = 0; i < vec.length; i++) sumSq += vec[i] * vec[i];
|
|
194
|
+
const norm = Math.sqrt(sumSq) || 1;
|
|
195
|
+
const out = new Float32Array(vec.length);
|
|
196
|
+
for (let i = 0; i < vec.length; i++) out[i] = vec[i] / norm;
|
|
197
|
+
return out;
|
|
198
|
+
}
|
|
199
|
+
function dot(a, b) {
|
|
200
|
+
const n = Math.min(a.length, b.length);
|
|
201
|
+
let s = 0;
|
|
202
|
+
for (let i = 0; i < n; i++) s += a[i] * b[i];
|
|
203
|
+
return s;
|
|
204
|
+
}
|
|
205
|
+
function clamp(x, lo, hi) {
|
|
206
|
+
return Math.min(hi, Math.max(lo, x));
|
|
207
|
+
}
|
|
208
|
+
function makePreview(text, maxLen = 240) {
|
|
209
|
+
const oneLine = text.replace(/\s+/g, " ").trim();
|
|
210
|
+
return oneLine.length <= maxLen ? oneLine : oneLine.slice(0, maxLen - 1) + "\u2026";
|
|
211
|
+
}
|
|
212
|
+
function nowMs() {
|
|
213
|
+
return Date.now();
|
|
214
|
+
}
|
|
215
|
+
function recencyScore(fileMtimeMs, halfLifeDays = 14) {
|
|
216
|
+
const ageMs = Math.max(0, nowMs() - fileMtimeMs);
|
|
217
|
+
const halfLifeMs = halfLifeDays * 24 * 60 * 60 * 1e3;
|
|
218
|
+
const score = Math.pow(0.5, ageMs / Math.max(1, halfLifeMs));
|
|
219
|
+
return clamp(score, 0, 1);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// src/retrieval/fts.ts
|
|
223
|
+
function ftsQueryFromText(input) {
|
|
224
|
+
const tokens = (input.match(/[A-Za-z0-9_]{2,}/g) ?? []).slice(0, 24);
|
|
225
|
+
if (tokens.length === 0) return "";
|
|
226
|
+
const parts = tokens.map((t) => {
|
|
227
|
+
const safe = t.replace(/"/g, '""');
|
|
228
|
+
return `${safe}*`;
|
|
229
|
+
});
|
|
230
|
+
return parts.join(" OR ");
|
|
231
|
+
}
|
|
232
|
+
function bm25ToScore01(bm25) {
|
|
233
|
+
if (!Number.isFinite(bm25)) return 0;
|
|
234
|
+
const s = 1 / (1 + Math.max(0, bm25));
|
|
235
|
+
return clamp(s, 0, 1);
|
|
236
|
+
}
|
|
237
|
+
function vectorCosineToScore01(cosine) {
|
|
238
|
+
if (!Number.isFinite(cosine)) return 0;
|
|
239
|
+
return clamp((cosine + 1) / 2, 0, 1);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/retrieval/tokens.ts
|
|
243
|
+
function uniq(xs) {
|
|
244
|
+
const out = [];
|
|
245
|
+
const s = /* @__PURE__ */ new Set();
|
|
246
|
+
for (const x of xs) {
|
|
247
|
+
if (!x) continue;
|
|
248
|
+
if (s.has(x)) continue;
|
|
249
|
+
s.add(x);
|
|
250
|
+
out.push(x);
|
|
251
|
+
}
|
|
252
|
+
return out;
|
|
253
|
+
}
|
|
254
|
+
function extractLexicalTokens(text, maxTokens = 2500) {
|
|
255
|
+
const toks = text.match(/[A-Za-z_][A-Za-z0-9_]{1,}/g) ?? [];
|
|
256
|
+
const u = uniq(toks).slice(0, maxTokens);
|
|
257
|
+
return u.join(" ");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/progress.ts
|
|
261
|
+
function toHandler(progress) {
|
|
262
|
+
if (!progress) return null;
|
|
263
|
+
if (typeof progress === "function") return progress;
|
|
264
|
+
if (typeof progress.emit === "function") return (e) => progress.emit(e);
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
var IndexerProgressObservable = class {
|
|
268
|
+
handlers = /* @__PURE__ */ new Set();
|
|
269
|
+
subscribe(handler) {
|
|
270
|
+
this.handlers.add(handler);
|
|
271
|
+
return () => this.handlers.delete(handler);
|
|
272
|
+
}
|
|
273
|
+
on(type, handler) {
|
|
274
|
+
const wrapped = (e) => {
|
|
275
|
+
if (e.type !== type) return;
|
|
276
|
+
handler(e);
|
|
277
|
+
};
|
|
278
|
+
return this.subscribe(wrapped);
|
|
279
|
+
}
|
|
280
|
+
emit(event) {
|
|
281
|
+
for (const h of this.handlers) {
|
|
282
|
+
try {
|
|
283
|
+
h(event);
|
|
284
|
+
} catch {
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
function asProgressSink(progress) {
|
|
290
|
+
const handler = toHandler(progress);
|
|
291
|
+
if (!handler) return null;
|
|
292
|
+
return { emit: handler };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/vector/bruteforce.ts
|
|
296
|
+
var BruteForceVectorIndex = class {
|
|
297
|
+
kind = "bruteforce";
|
|
298
|
+
metric = "cosine";
|
|
299
|
+
dimension = 0;
|
|
300
|
+
ids = [];
|
|
301
|
+
vecs = [];
|
|
302
|
+
pos = /* @__PURE__ */ new Map();
|
|
303
|
+
async init(init) {
|
|
304
|
+
this.metric = init.metric;
|
|
305
|
+
this.dimension = init.dimension;
|
|
306
|
+
}
|
|
307
|
+
async upsert(points) {
|
|
308
|
+
for (const p of points) this.upsertOne(p.id, p.vector);
|
|
309
|
+
}
|
|
310
|
+
upsertOne(id, vec) {
|
|
311
|
+
const v = normalise(vec);
|
|
312
|
+
const existing = this.pos.get(id);
|
|
313
|
+
if (existing !== void 0) {
|
|
314
|
+
this.vecs[existing] = v;
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
this.pos.set(id, this.ids.length);
|
|
318
|
+
this.ids.push(id);
|
|
319
|
+
this.vecs.push(v);
|
|
320
|
+
}
|
|
321
|
+
async remove(ids) {
|
|
322
|
+
for (const id of ids) this.removeOne(id);
|
|
323
|
+
}
|
|
324
|
+
removeOne(id) {
|
|
325
|
+
const i = this.pos.get(id);
|
|
326
|
+
if (i === void 0) return;
|
|
327
|
+
const last = this.ids.length - 1;
|
|
328
|
+
if (i !== last) {
|
|
329
|
+
const lastId = this.ids[last];
|
|
330
|
+
this.ids[i] = lastId;
|
|
331
|
+
this.vecs[i] = this.vecs[last];
|
|
332
|
+
this.pos.set(lastId, i);
|
|
333
|
+
}
|
|
334
|
+
this.ids.pop();
|
|
335
|
+
this.vecs.pop();
|
|
336
|
+
this.pos.delete(id);
|
|
337
|
+
}
|
|
338
|
+
async rebuild(points) {
|
|
339
|
+
this.ids = [];
|
|
340
|
+
this.vecs = [];
|
|
341
|
+
this.pos = /* @__PURE__ */ new Map();
|
|
342
|
+
for (const p of points) this.upsertOne(p.id, p.vector);
|
|
343
|
+
}
|
|
344
|
+
async search(query, k) {
|
|
345
|
+
const q = normalise(query);
|
|
346
|
+
const top = [];
|
|
347
|
+
for (let i = 0; i < this.ids.length; i++) {
|
|
348
|
+
const s = dot(q, this.vecs[i]);
|
|
349
|
+
if (top.length < k) {
|
|
350
|
+
top.push({ id: this.ids[i], score: s });
|
|
351
|
+
top.sort((a, b) => b.score - a.score);
|
|
352
|
+
} else if (s > top[top.length - 1].score) {
|
|
353
|
+
top[top.length - 1] = { id: this.ids[i], score: s };
|
|
354
|
+
top.sort((a, b) => b.score - a.score);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return top;
|
|
358
|
+
}
|
|
359
|
+
async count() {
|
|
360
|
+
return this.ids.length;
|
|
361
|
+
}
|
|
362
|
+
async flush() {
|
|
363
|
+
}
|
|
364
|
+
async close() {
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
// src/browser/chunker.ts
|
|
369
|
+
function languageFromPath(posixPath) {
|
|
370
|
+
const ext = posixPath.toLowerCase().split(".").pop() ?? "";
|
|
371
|
+
if (["ts", "tsx"].includes(ext)) return "typescript";
|
|
372
|
+
if (["js", "jsx", "mjs", "cjs"].includes(ext)) return "javascript";
|
|
373
|
+
if (["py"].includes(ext)) return "python";
|
|
374
|
+
if (["go"].includes(ext)) return "go";
|
|
375
|
+
if (["ctl", "ltl", "isl"].includes(ext)) return ext;
|
|
376
|
+
if (["ispec"].includes(ext)) return "isl";
|
|
377
|
+
if (["ca", "cpnexpr"].includes(ext)) return "colour-algebra";
|
|
378
|
+
if (["rs"].includes(ext)) return "rust";
|
|
379
|
+
if (["java"].includes(ext)) return "java";
|
|
380
|
+
if (["kt", "kts"].includes(ext)) return "kotlin";
|
|
381
|
+
if (["cs"].includes(ext)) return "csharp";
|
|
382
|
+
if (["md"].includes(ext)) return "markdown";
|
|
383
|
+
if (["json", "yaml", "yml", "toml"].includes(ext)) return "config";
|
|
384
|
+
return "text";
|
|
385
|
+
}
|
|
386
|
+
function chunkByLines(sourceText, cfg) {
|
|
387
|
+
const lines = sourceText.split(/\r?\n/);
|
|
388
|
+
const out = [];
|
|
389
|
+
const step = Math.max(1, cfg.maxLines - cfg.overlapLines);
|
|
390
|
+
for (let start = 0; start < lines.length; start += step) {
|
|
391
|
+
const end = Math.min(lines.length, start + cfg.maxLines);
|
|
392
|
+
const text = lines.slice(start, end).join("\n");
|
|
393
|
+
if (!text.trim()) continue;
|
|
394
|
+
out.push({
|
|
395
|
+
startLine: start + 1,
|
|
396
|
+
endLine: end,
|
|
397
|
+
text,
|
|
398
|
+
contentHash: sha256Hex(text),
|
|
399
|
+
tokens: estimateTokens(text)
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
return out;
|
|
403
|
+
}
|
|
404
|
+
function splitIfTooLarge(ch, cfg) {
|
|
405
|
+
if (ch.text.length <= cfg.maxChars) return [ch];
|
|
406
|
+
return chunkByLines(ch.text, cfg).map((sub) => ({
|
|
407
|
+
...sub,
|
|
408
|
+
startLine: ch.startLine + (sub.startLine - 1),
|
|
409
|
+
endLine: ch.startLine + (sub.endLine - 1)
|
|
410
|
+
}));
|
|
411
|
+
}
|
|
412
|
+
function chunkSource(posixPath, sourceText, cfg) {
|
|
413
|
+
const language = languageFromPath(posixPath);
|
|
414
|
+
const chunks = chunkByLines(sourceText, cfg).flatMap((ch) => splitIfTooLarge(ch, cfg));
|
|
415
|
+
return { language, chunks };
|
|
416
|
+
}
|
|
417
|
+
export {
|
|
418
|
+
BruteForceVectorIndex,
|
|
419
|
+
DEFAULT_PROFILES,
|
|
420
|
+
HashEmbeddingsProvider,
|
|
421
|
+
IndexerProgressObservable,
|
|
422
|
+
OllamaEmbeddingsProvider,
|
|
423
|
+
OpenAIEmbeddingsProvider,
|
|
424
|
+
asProgressSink,
|
|
425
|
+
bm25ToScore01,
|
|
426
|
+
chunkSource,
|
|
427
|
+
clamp,
|
|
428
|
+
deepMergeProfile,
|
|
429
|
+
dot,
|
|
430
|
+
estimateTokens,
|
|
431
|
+
extractLexicalTokens,
|
|
432
|
+
fromPosixPath,
|
|
433
|
+
ftsQueryFromText,
|
|
434
|
+
languageFromPath,
|
|
435
|
+
makePreview,
|
|
436
|
+
normalise,
|
|
437
|
+
nowMs,
|
|
438
|
+
recencyScore,
|
|
439
|
+
sha256Hex,
|
|
440
|
+
toPosixPath,
|
|
441
|
+
vectorCosineToScore01
|
|
442
|
+
};
|