@reposkein/mcp 0.7.0 → 0.9.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 +1 -0
- package/binary-digests.json +4 -4
- package/dist/SKILL.md +22 -0
- package/dist/cli/doctor.d.ts +2 -2
- package/dist/cli/doctor.js +8 -4
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/doctorFreshness.d.ts +6 -0
- package/dist/cli/doctorFreshness.js +23 -0
- package/dist/cli/doctorFreshness.js.map +1 -1
- package/dist/cli/migrate.d.ts +26 -0
- package/dist/cli/migrate.js +208 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/embed/batch.d.ts +47 -0
- package/dist/embed/batch.js +92 -0
- package/dist/embed/batch.js.map +1 -0
- package/dist/embed/cache.d.ts +22 -48
- package/dist/embed/cache.js +44 -164
- package/dist/embed/cache.js.map +1 -1
- package/dist/embed/corpusVectors.d.ts +20 -0
- package/dist/embed/corpusVectors.js +60 -0
- package/dist/embed/corpusVectors.js.map +1 -0
- package/dist/embed/provider.d.ts +21 -2
- package/dist/embed/provider.js.map +1 -1
- package/dist/embed/providers/http.d.ts +3 -2
- package/dist/embed/providers/http.js +14 -1
- package/dist/embed/providers/http.js.map +1 -1
- package/dist/embed/providers/voyage.d.ts +3 -2
- package/dist/embed/providers/voyage.js +50 -54
- package/dist/embed/providers/voyage.js.map +1 -1
- package/dist/embed/vectorStore.d.ts +89 -0
- package/dist/embed/vectorStore.js +267 -0
- package/dist/embed/vectorStore.js.map +1 -0
- package/dist/guard/caps.d.ts +3 -0
- package/dist/guard/caps.js +4 -1
- package/dist/guard/caps.js.map +1 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/search/bm25f.d.ts +17 -1
- package/dist/search/bm25f.js +89 -53
- package/dist/search/bm25f.js.map +1 -1
- package/dist/store/GraphStore.d.ts +6 -1
- package/dist/store/JsonlGraphStore.d.ts +47 -10
- package/dist/store/JsonlGraphStore.js +129 -50
- package/dist/store/JsonlGraphStore.js.map +1 -1
- package/dist/store/Neo4jGraphStore.d.ts +11 -0
- package/dist/store/Neo4jGraphStore.js +29 -2
- package/dist/store/Neo4jGraphStore.js.map +1 -1
- package/dist/store/instrumentTool.d.ts +9 -1
- package/dist/store/instrumentTool.js +33 -2
- package/dist/store/instrumentTool.js.map +1 -1
- package/dist/store/jsonlGraph.d.ts +22 -0
- package/dist/store/jsonlGraph.js +75 -18
- package/dist/store/jsonlGraph.js.map +1 -1
- package/dist/store/jsonlLines.d.ts +21 -0
- package/dist/store/jsonlLines.js +64 -0
- package/dist/store/jsonlLines.js.map +1 -0
- package/dist/store/repoSession.d.ts +19 -0
- package/dist/store/repoSession.js +25 -0
- package/dist/store/repoSession.js.map +1 -1
- package/dist/store/trackedGraph.d.ts +14 -0
- package/dist/store/trackedGraph.js +39 -0
- package/dist/store/trackedGraph.js.map +1 -0
- package/dist/tools/readCypher.js +9 -2
- package/dist/tools/readCypher.js.map +1 -1
- package/dist/tools/semanticFind.js +9 -6
- package/dist/tools/semanticFind.js.map +1 -1
- package/package.json +1 -1
package/dist/embed/cache.d.ts
CHANGED
|
@@ -1,35 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* How a corpus node becomes a document string, and how that string is keyed.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* —
|
|
4
|
+
* Storage itself lives in vectorStore.ts — fixed-stride float32 beside a JSONL
|
|
5
|
+
* index — and the orchestration in corpusVectors.ts. This file is only the
|
|
6
|
+
* text: what we embed, and the hash that decides when to re-embed it.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* sole per-row invalidation key. It covers all code/summary changes since the doc
|
|
13
|
-
* string is built from the same fields (qualified_name + signature + summary + file_path).
|
|
14
|
-
*
|
|
15
|
-
* Mirrors the atomic-write + best-effort pattern from mcp/src/store/sidecar.ts.
|
|
16
|
-
* Any I/O or provider failure in embedCorpus must NOT propagate — callers catch and
|
|
17
|
-
* fall back to the lexical result.
|
|
8
|
+
* Invalidation: `doc_hash` must match the hash of a freshly-built document
|
|
9
|
+
* string, so a change to qualified_name, signature, semantic_summary or
|
|
10
|
+
* file_path re-embeds the node. CorpusNode does not expose the committed
|
|
11
|
+
* content_hash, so this is the sole per-row key — which is sufficient, since
|
|
12
|
+
* the document is built from exactly those fields.
|
|
18
13
|
*/
|
|
19
|
-
import type { EmbeddingProvider } from "./provider.js";
|
|
20
14
|
import type { CorpusNode } from "../store/GraphStore.js";
|
|
21
|
-
/** One cached record per embedded node. */
|
|
22
|
-
export interface EmbedRecord {
|
|
23
|
-
id: string;
|
|
24
|
-
/** doc_hash: SHA-256 of the embedded document string (invalidation key). */
|
|
25
|
-
doc_hash: string;
|
|
26
|
-
v: number[];
|
|
27
|
-
}
|
|
28
15
|
/** Build the document string for a corpus node (deterministic, same for all calls).
|
|
29
16
|
* voyage-code-3 is code-specialized, so including code-ish context plays to its strength.
|
|
30
17
|
* Document = qualified_name + optional signature + optional summary + file_path.
|
|
31
18
|
*/
|
|
32
|
-
export declare function buildDocString(node: CorpusNode): string;
|
|
19
|
+
export declare function buildDocString(node: CorpusNode, budget?: number): string;
|
|
20
|
+
/**
|
|
21
|
+
* Longest document string we will hand a provider.
|
|
22
|
+
*
|
|
23
|
+
* This is a correctness bound, not a preference. The bundled embedding server
|
|
24
|
+
* rejects an over-long input with 413 (EMBED_MAX_INPUT_CHARS, default 8000),
|
|
25
|
+
* and one rejected document fails the whole embed call — so `semantic_find`
|
|
26
|
+
* would fall back to lexical, and keep falling back, because the offending
|
|
27
|
+
* document is never embedded and every later attempt reissues it. Keep this at
|
|
28
|
+
* or below the server's cap.
|
|
29
|
+
*/
|
|
30
|
+
export declare const DEFAULT_DOC_CHAR_BUDGET = 8000;
|
|
31
|
+
export declare function docCharBudget(env?: NodeJS.ProcessEnv): number;
|
|
33
32
|
/** SHA-256 of a string, hex-encoded. */
|
|
34
33
|
export declare function sha256(s: string): string;
|
|
35
34
|
/**
|
|
@@ -39,28 +38,3 @@ export declare function sha256(s: string): string;
|
|
|
39
38
|
* the FS. Replace any run of unsafe characters with "_".
|
|
40
39
|
*/
|
|
41
40
|
export declare function sanitizeModelId(modelId: string): string;
|
|
42
|
-
/** Derive the cache file path for a given repo root + provider. */
|
|
43
|
-
export declare function cachePath(repoPath: string, provider: EmbeddingProvider): string;
|
|
44
|
-
/**
|
|
45
|
-
* Load cache into a Map keyed by node id. Missing file → empty map. Best-effort.
|
|
46
|
-
*
|
|
47
|
-
* Row validation: any row whose `v` is not an array of finite numbers of the
|
|
48
|
-
* correct length (matching provider.dims) is dropped — treated as a miss so
|
|
49
|
-
* it will be re-embedded. Pass `expectedDims` to enable dim-length validation;
|
|
50
|
-
* omit (undefined) to skip the length check (e.g. when the provider is not known
|
|
51
|
-
* at load time — but the embedCorpus function always passes it).
|
|
52
|
-
*/
|
|
53
|
-
export declare function loadCache(path: string, expectedDims?: number): Map<string, EmbedRecord>;
|
|
54
|
-
/** Rewrite the cache file (sorted by id). Atomic: write to .tmp then rename. Best-effort. */
|
|
55
|
-
export declare function saveCache(path: string, records: Map<string, EmbedRecord>): void;
|
|
56
|
-
/**
|
|
57
|
-
* Embed the corpus nodes using the provider, leveraging the cache for nodes
|
|
58
|
-
* whose doc_hash hasn't changed.
|
|
59
|
-
*
|
|
60
|
-
* Returns a Map<id, vector> for all nodes in corpus.
|
|
61
|
-
* Only embeds nodes whose cache entry is missing or stale.
|
|
62
|
-
* Persists updated cache to disk.
|
|
63
|
-
*
|
|
64
|
-
* Throws on embedding failure — callers must catch and fall back to lexical.
|
|
65
|
-
*/
|
|
66
|
-
export declare function embedCorpus(provider: EmbeddingProvider, repoPath: string, corpus: CorpusNode[]): Promise<Map<string, number[]>>;
|
package/dist/embed/cache.js
CHANGED
|
@@ -1,36 +1,57 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* How a corpus node becomes a document string, and how that string is keyed.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* —
|
|
4
|
+
* Storage itself lives in vectorStore.ts — fixed-stride float32 beside a JSONL
|
|
5
|
+
* index — and the orchestration in corpusVectors.ts. This file is only the
|
|
6
|
+
* text: what we embed, and the hash that decides when to re-embed it.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* sole per-row invalidation key. It covers all code/summary changes since the doc
|
|
13
|
-
* string is built from the same fields (qualified_name + signature + summary + file_path).
|
|
14
|
-
*
|
|
15
|
-
* Mirrors the atomic-write + best-effort pattern from mcp/src/store/sidecar.ts.
|
|
16
|
-
* Any I/O or provider failure in embedCorpus must NOT propagate — callers catch and
|
|
17
|
-
* fall back to the lexical result.
|
|
8
|
+
* Invalidation: `doc_hash` must match the hash of a freshly-built document
|
|
9
|
+
* string, so a change to qualified_name, signature, semantic_summary or
|
|
10
|
+
* file_path re-embeds the node. CorpusNode does not expose the committed
|
|
11
|
+
* content_hash, so this is the sole per-row key — which is sufficient, since
|
|
12
|
+
* the document is built from exactly those fields.
|
|
18
13
|
*/
|
|
19
|
-
import { existsSync, readFileSync, writeFileSync, renameSync, unlinkSync, mkdirSync } from "node:fs";
|
|
20
|
-
import { join, dirname } from "node:path";
|
|
21
14
|
import { createHash } from "node:crypto";
|
|
22
15
|
/** Build the document string for a corpus node (deterministic, same for all calls).
|
|
23
16
|
* voyage-code-3 is code-specialized, so including code-ish context plays to its strength.
|
|
24
17
|
* Document = qualified_name + optional signature + optional summary + file_path.
|
|
25
18
|
*/
|
|
26
|
-
export function buildDocString(node) {
|
|
27
|
-
const
|
|
19
|
+
export function buildDocString(node, budget = docCharBudget()) {
|
|
20
|
+
const head = [node.qualified_name];
|
|
28
21
|
if (node.signature)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
head.push(node.signature);
|
|
23
|
+
const tail = [node.file_path];
|
|
24
|
+
// Trim the SUMMARY to fit, not the tail. It is the one unbounded field —
|
|
25
|
+
// agents author it — and the identifiers are what a search matches on.
|
|
26
|
+
const overhead = [...head, ...tail].join("\n").length + (node.summary ? 1 : 0);
|
|
27
|
+
let summary = node.summary ?? "";
|
|
28
|
+
if (overhead + summary.length > budget) {
|
|
29
|
+
summary = summary.slice(0, Math.max(0, budget - overhead));
|
|
30
|
+
}
|
|
31
|
+
const parts = [...head];
|
|
32
|
+
if (summary)
|
|
33
|
+
parts.push(summary);
|
|
34
|
+
parts.push(...tail);
|
|
35
|
+
// Last resort, for a node whose own name and path already exceed the budget.
|
|
36
|
+
return parts.join("\n").slice(0, budget);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Longest document string we will hand a provider.
|
|
40
|
+
*
|
|
41
|
+
* This is a correctness bound, not a preference. The bundled embedding server
|
|
42
|
+
* rejects an over-long input with 413 (EMBED_MAX_INPUT_CHARS, default 8000),
|
|
43
|
+
* and one rejected document fails the whole embed call — so `semantic_find`
|
|
44
|
+
* would fall back to lexical, and keep falling back, because the offending
|
|
45
|
+
* document is never embedded and every later attempt reissues it. Keep this at
|
|
46
|
+
* or below the server's cap.
|
|
47
|
+
*/
|
|
48
|
+
export const DEFAULT_DOC_CHAR_BUDGET = 8000;
|
|
49
|
+
export function docCharBudget(env = process.env) {
|
|
50
|
+
const raw = env["REPOSKEIN_EMBED_MAX_INPUT_CHARS"];
|
|
51
|
+
if (raw === undefined)
|
|
52
|
+
return DEFAULT_DOC_CHAR_BUDGET;
|
|
53
|
+
const n = Number(raw);
|
|
54
|
+
return Number.isInteger(n) && n > 0 ? n : DEFAULT_DOC_CHAR_BUDGET;
|
|
34
55
|
}
|
|
35
56
|
/** SHA-256 of a string, hex-encoded. */
|
|
36
57
|
export function sha256(s) {
|
|
@@ -47,145 +68,4 @@ export function sanitizeModelId(modelId) {
|
|
|
47
68
|
// Also collapse multiple consecutive underscores to avoid "___"-confusing names.
|
|
48
69
|
return modelId.replace(/[/\\:*?"<>|\x00-\x1f]+/g, "_");
|
|
49
70
|
}
|
|
50
|
-
/** Derive the cache file path for a given repo root + provider. */
|
|
51
|
-
export function cachePath(repoPath, provider) {
|
|
52
|
-
const safeModel = sanitizeModelId(provider.modelId());
|
|
53
|
-
const name = `${provider.id()}__${safeModel}__d${provider.dims()}`;
|
|
54
|
-
return join(repoPath, ".reposkein", "local", "embeddings", `${name}.jsonl`);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Load cache into a Map keyed by node id. Missing file → empty map. Best-effort.
|
|
58
|
-
*
|
|
59
|
-
* Row validation: any row whose `v` is not an array of finite numbers of the
|
|
60
|
-
* correct length (matching provider.dims) is dropped — treated as a miss so
|
|
61
|
-
* it will be re-embedded. Pass `expectedDims` to enable dim-length validation;
|
|
62
|
-
* omit (undefined) to skip the length check (e.g. when the provider is not known
|
|
63
|
-
* at load time — but the embedCorpus function always passes it).
|
|
64
|
-
*/
|
|
65
|
-
export function loadCache(path, expectedDims) {
|
|
66
|
-
const map = new Map();
|
|
67
|
-
if (!existsSync(path))
|
|
68
|
-
return map;
|
|
69
|
-
let text;
|
|
70
|
-
try {
|
|
71
|
-
text = readFileSync(path, "utf8");
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
return map;
|
|
75
|
-
}
|
|
76
|
-
for (const line of text.split("\n")) {
|
|
77
|
-
if (line.trim() === "")
|
|
78
|
-
continue;
|
|
79
|
-
try {
|
|
80
|
-
const o = JSON.parse(line);
|
|
81
|
-
if (typeof o["id"] === "string" &&
|
|
82
|
-
typeof o["doc_hash"] === "string" &&
|
|
83
|
-
Array.isArray(o["v"])) {
|
|
84
|
-
const v = o["v"];
|
|
85
|
-
// Validate: every element must be a finite number
|
|
86
|
-
const allFinite = v.every((x) => typeof x === "number" && isFinite(x));
|
|
87
|
-
if (!allFinite)
|
|
88
|
-
continue; // corrupt row — drop it (will be re-embedded)
|
|
89
|
-
// Validate: length must match the expected dims (when known)
|
|
90
|
-
if (expectedDims !== undefined && v.length !== expectedDims)
|
|
91
|
-
continue;
|
|
92
|
-
map.set(o["id"], {
|
|
93
|
-
id: o["id"],
|
|
94
|
-
doc_hash: o["doc_hash"],
|
|
95
|
-
v: v,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
// skip malformed line
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return map;
|
|
104
|
-
}
|
|
105
|
-
/** Rewrite the cache file (sorted by id). Atomic: write to .tmp then rename. Best-effort. */
|
|
106
|
-
export function saveCache(path, records) {
|
|
107
|
-
const lines = [...records.keys()].sort().map((id) => {
|
|
108
|
-
const r = records.get(id);
|
|
109
|
-
return JSON.stringify({ id: r.id, doc_hash: r.doc_hash, v: r.v });
|
|
110
|
-
});
|
|
111
|
-
const tmp = `${path}.tmp`;
|
|
112
|
-
try {
|
|
113
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
114
|
-
writeFileSync(tmp, lines.length ? lines.join("\n") + "\n" : "");
|
|
115
|
-
renameSync(tmp, path);
|
|
116
|
-
}
|
|
117
|
-
catch {
|
|
118
|
-
// best-effort; write failure must not break the tool call
|
|
119
|
-
try {
|
|
120
|
-
if (existsSync(tmp))
|
|
121
|
-
unlinkSync(tmp);
|
|
122
|
-
}
|
|
123
|
-
catch { /* ignore */ }
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Embed the corpus nodes using the provider, leveraging the cache for nodes
|
|
128
|
-
* whose doc_hash hasn't changed.
|
|
129
|
-
*
|
|
130
|
-
* Returns a Map<id, vector> for all nodes in corpus.
|
|
131
|
-
* Only embeds nodes whose cache entry is missing or stale.
|
|
132
|
-
* Persists updated cache to disk.
|
|
133
|
-
*
|
|
134
|
-
* Throws on embedding failure — callers must catch and fall back to lexical.
|
|
135
|
-
*/
|
|
136
|
-
export async function embedCorpus(provider, repoPath, corpus) {
|
|
137
|
-
const path = cachePath(repoPath, provider);
|
|
138
|
-
const cache = loadCache(path, provider.dims());
|
|
139
|
-
// Compute document strings + hashes for all corpus nodes
|
|
140
|
-
const docStrings = new Map();
|
|
141
|
-
const docHashes = new Map();
|
|
142
|
-
for (const node of corpus) {
|
|
143
|
-
const doc = buildDocString(node);
|
|
144
|
-
docStrings.set(node.id, doc);
|
|
145
|
-
docHashes.set(node.id, sha256(doc));
|
|
146
|
-
}
|
|
147
|
-
// Identify which nodes need embedding (cache miss or stale doc_hash)
|
|
148
|
-
const toEmbed = [];
|
|
149
|
-
for (const node of corpus) {
|
|
150
|
-
const cached = cache.get(node.id);
|
|
151
|
-
const isHit = cached !== undefined && cached.doc_hash === docHashes.get(node.id);
|
|
152
|
-
if (!isHit) {
|
|
153
|
-
toEmbed.push(node);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// Embed only misses
|
|
157
|
-
if (toEmbed.length > 0) {
|
|
158
|
-
const texts = toEmbed.map((n) => docStrings.get(n.id));
|
|
159
|
-
const vectors = await provider.embed(texts, "document");
|
|
160
|
-
// Guard: provider must return exactly as many vectors as we sent.
|
|
161
|
-
// A count mismatch means the provider is broken or mis-aligned — throw so
|
|
162
|
-
// the caller's try/catch falls back to lexical. Never write corrupt data.
|
|
163
|
-
if (vectors.length !== toEmbed.length) {
|
|
164
|
-
throw new Error(`Embedding provider returned ${vectors.length} vectors for ${toEmbed.length} texts — count mismatch; refusing to cache`);
|
|
165
|
-
}
|
|
166
|
-
const expectedDims = provider.dims();
|
|
167
|
-
for (let i = 0; i < toEmbed.length; i++) {
|
|
168
|
-
const vec = vectors[i];
|
|
169
|
-
if (!Array.isArray(vec) || vec.length !== expectedDims) {
|
|
170
|
-
throw new Error(`Embedding provider returned a vector with ${Array.isArray(vec) ? vec.length : "undefined"} dims at index ${i}; expected ${expectedDims} — refusing to cache`);
|
|
171
|
-
}
|
|
172
|
-
const node = toEmbed[i];
|
|
173
|
-
cache.set(node.id, {
|
|
174
|
-
id: node.id,
|
|
175
|
-
doc_hash: docHashes.get(node.id),
|
|
176
|
-
v: vec,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
saveCache(path, cache);
|
|
180
|
-
}
|
|
181
|
-
// Build result map for all corpus nodes
|
|
182
|
-
const result = new Map();
|
|
183
|
-
for (const node of corpus) {
|
|
184
|
-
const rec = cache.get(node.id);
|
|
185
|
-
if (rec) {
|
|
186
|
-
result.set(node.id, rec.v);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
return result;
|
|
190
|
-
}
|
|
191
71
|
//# sourceMappingURL=cache.js.map
|
package/dist/embed/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/embed/cache.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/embed/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAgB,EAAE,MAAM,GAAG,aAAa,EAAE;IACvE,MAAM,IAAI,GAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,IAAI,CAAC,SAAS;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAExC,yEAAyE;IACzE,uEAAuE;IACvE,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACjC,IAAI,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;QACvC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACxB,IAAI,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACpB,6EAA6E;IAC7E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAE5C,MAAM,UAAU,aAAa,CAAC,MAAyB,OAAO,CAAC,GAAG;IAChE,MAAM,GAAG,GAAG,GAAG,CAAC,iCAAiC,CAAC,CAAC;IACnD,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,uBAAuB,CAAC;IACtD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAC;AACpE,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,MAAM,CAAC,CAAS;IAC9B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,oEAAoE;IACpE,iFAAiF;IACjF,OAAO,OAAO,CAAC,OAAO,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corpus vectors for `semantic_find`, behind the vector store.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the JSON cache's "hand me every vector as number[]" shape. Callers
|
|
5
|
+
* get a store they can ask for a ranked top-k; they never hold the corpus.
|
|
6
|
+
*/
|
|
7
|
+
import type { EmbeddingProvider } from "./provider.js";
|
|
8
|
+
import { type VectorStore } from "./vectorStore.js";
|
|
9
|
+
import type { CorpusNode } from "../store/GraphStore.js";
|
|
10
|
+
/** Base path (no extension) for a provider's vectors in this repo. */
|
|
11
|
+
export declare function vectorBasePath(repoPath: string, provider: EmbeddingProvider): string;
|
|
12
|
+
/**
|
|
13
|
+
* Ensure every corpus node has a current vector, and return the store.
|
|
14
|
+
*
|
|
15
|
+
* Only misses are embedded, in bounded batches, each flushed as it lands so an
|
|
16
|
+
* interrupted cold run resumes rather than restarting.
|
|
17
|
+
*
|
|
18
|
+
* Throws on embedding failure — callers catch and fall back to lexical.
|
|
19
|
+
*/
|
|
20
|
+
export declare function ensureCorpusVectors(provider: EmbeddingProvider, repoPath: string, corpus: CorpusNode[]): Promise<VectorStore>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corpus vectors for `semantic_find`, behind the vector store.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the JSON cache's "hand me every vector as number[]" shape. Callers
|
|
5
|
+
* get a store they can ask for a ranked top-k; they never hold the corpus.
|
|
6
|
+
*/
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { embedInBatches } from "./batch.js";
|
|
9
|
+
import { buildDocString, sanitizeModelId, sha256 } from "./cache.js";
|
|
10
|
+
import { openVectorStore, removeLegacyJsonCache } from "./vectorStore.js";
|
|
11
|
+
/** Base path (no extension) for a provider's vectors in this repo. */
|
|
12
|
+
export function vectorBasePath(repoPath, provider) {
|
|
13
|
+
const name = `${provider.id()}__${sanitizeModelId(provider.modelId())}__d${provider.dims()}`;
|
|
14
|
+
return join(repoPath, ".reposkein", "local", "embeddings", name);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Ensure every corpus node has a current vector, and return the store.
|
|
18
|
+
*
|
|
19
|
+
* Only misses are embedded, in bounded batches, each flushed as it lands so an
|
|
20
|
+
* interrupted cold run resumes rather than restarting.
|
|
21
|
+
*
|
|
22
|
+
* Throws on embedding failure — callers catch and fall back to lexical.
|
|
23
|
+
*/
|
|
24
|
+
export async function ensureCorpusVectors(provider, repoPath, corpus) {
|
|
25
|
+
const base = vectorBasePath(repoPath, provider);
|
|
26
|
+
// The pre-binary cache is superseded, and at 200k nodes it was over 4 GB of
|
|
27
|
+
// dead JSON. Drop it the first time we write the store beside it.
|
|
28
|
+
removeLegacyJsonCache(base);
|
|
29
|
+
const store = openVectorStore(base, provider.dims());
|
|
30
|
+
const docs = new Map();
|
|
31
|
+
const hashes = new Map();
|
|
32
|
+
const misses = [];
|
|
33
|
+
for (const node of corpus) {
|
|
34
|
+
const doc = buildDocString(node);
|
|
35
|
+
docs.set(node.id, doc);
|
|
36
|
+
const hash = sha256(doc);
|
|
37
|
+
hashes.set(node.id, hash);
|
|
38
|
+
if (store.docHash(node.id) !== hash)
|
|
39
|
+
misses.push(node);
|
|
40
|
+
}
|
|
41
|
+
if (misses.length === 0)
|
|
42
|
+
return store;
|
|
43
|
+
const texts = misses.map((n) => docs.get(n.id));
|
|
44
|
+
const expectedDims = provider.dims();
|
|
45
|
+
await embedInBatches(provider, texts, "document", (offset, vectors) => {
|
|
46
|
+
const batch = [];
|
|
47
|
+
for (let i = 0; i < vectors.length; i++) {
|
|
48
|
+
const vec = vectors[i];
|
|
49
|
+
if (!Array.isArray(vec) || vec.length !== expectedDims) {
|
|
50
|
+
throw new Error(`Embedding provider returned a vector with ${Array.isArray(vec) ? vec.length : "undefined"} dims at index ${offset + i}; expected ${expectedDims} — refusing to store`);
|
|
51
|
+
}
|
|
52
|
+
const node = misses[offset + i];
|
|
53
|
+
batch.push({ id: node.id, docHash: hashes.get(node.id), vector: vec });
|
|
54
|
+
}
|
|
55
|
+
store.upsertMany(batch);
|
|
56
|
+
store.flush();
|
|
57
|
+
});
|
|
58
|
+
return store;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=corpusVectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpusVectors.js","sourceRoot":"","sources":["../../src/embed/corpusVectors.ts"],"names":[],"mappings":"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"}
|
package/dist/embed/provider.d.ts
CHANGED
|
@@ -12,6 +12,19 @@
|
|
|
12
12
|
* REPOSKEIN_EMBED_URL base URL for http provider
|
|
13
13
|
*/
|
|
14
14
|
export type EmbedKind = "document" | "query";
|
|
15
|
+
/**
|
|
16
|
+
* What a single request to this provider may carry.
|
|
17
|
+
*
|
|
18
|
+
* The shared batcher (embed/batch.ts) enforces these; an adapter never chunks
|
|
19
|
+
* for itself. `maxTokens` is measured with estimateTokens, a deterministic
|
|
20
|
+
* length heuristic — it is a memory budget, not a billing figure.
|
|
21
|
+
*/
|
|
22
|
+
export interface BatchLimits {
|
|
23
|
+
/** Max texts in one request. */
|
|
24
|
+
maxItems: number;
|
|
25
|
+
/** Max estimated tokens across one request's texts. */
|
|
26
|
+
maxTokens: number;
|
|
27
|
+
}
|
|
15
28
|
export interface EmbeddingProvider {
|
|
16
29
|
/** Stable provider id, e.g. "voyage". Forms part of the cache key. */
|
|
17
30
|
id(): string;
|
|
@@ -19,13 +32,19 @@ export interface EmbeddingProvider {
|
|
|
19
32
|
modelId(): string;
|
|
20
33
|
/** Output vector dimensionality, e.g. 1024. Part of the cache key. */
|
|
21
34
|
dims(): number;
|
|
35
|
+
/** Per-request limits. Callers go through embedInBatches, which enforces them. */
|
|
36
|
+
limits(): BatchLimits;
|
|
22
37
|
/**
|
|
23
|
-
* Embed
|
|
38
|
+
* Embed ONE request's worth of texts. Implementations must NOT batch
|
|
39
|
+
* internally: the caller has already sized this call against limits().
|
|
40
|
+
* Splitting here would put the memory bound back inside each adapter, which
|
|
41
|
+
* is exactly how the local HTTP adapter came to send whole corpora at once.
|
|
42
|
+
*
|
|
24
43
|
* kind maps to Voyage's input_type ("document" vs "query") — Voyage uses
|
|
25
44
|
* asymmetric embeddings so this materially changes the vectors.
|
|
26
45
|
* Returns one number[] per input, in order.
|
|
27
46
|
*/
|
|
28
|
-
|
|
47
|
+
embedBatch(texts: string[], kind: EmbedKind): Promise<number[][]>;
|
|
29
48
|
}
|
|
30
49
|
/**
|
|
31
50
|
* Build a provider from env vars, or null if embeddings are disabled (default).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/embed/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/embed/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAwCH;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;IACxE,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,0BAA0B,CAAC,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/E,IAAI,YAAY,KAAK,MAAM,IAAI,YAAY,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAEhE,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,EAAE,uBAAuB,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAC1E,OAAO,IAAI,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;QAC5B,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACtE,OAAO,IAAI,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,IAAI,KAAK,CACb,sCAAsC,YAAY,kCAAkC,CACrF,CAAC;AACJ,CAAC"}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* REPOSKEIN_EMBED_MODEL (required; e.g. "voyage-4-nano")
|
|
22
22
|
* REPOSKEIN_EMBED_DIMS (required; output dimension of the local model)
|
|
23
23
|
*/
|
|
24
|
-
import type { EmbeddingProvider, EmbedKind } from "../provider.js";
|
|
24
|
+
import type { EmbeddingProvider, EmbedKind, BatchLimits } from "../provider.js";
|
|
25
25
|
export declare class HttpEmbeddingProvider implements EmbeddingProvider {
|
|
26
26
|
private readonly _id;
|
|
27
27
|
private readonly _url;
|
|
@@ -32,5 +32,6 @@ export declare class HttpEmbeddingProvider implements EmbeddingProvider {
|
|
|
32
32
|
id(): string;
|
|
33
33
|
modelId(): string;
|
|
34
34
|
dims(): number;
|
|
35
|
-
|
|
35
|
+
limits(): BatchLimits;
|
|
36
|
+
embedBatch(texts: string[], kind: EmbedKind): Promise<number[][]>;
|
|
36
37
|
}
|
|
@@ -24,6 +24,16 @@
|
|
|
24
24
|
const DEFAULT_DIMS = 1024;
|
|
25
25
|
/** Default embedding request timeout in ms. Override with REPOSKEIN_EMBED_TIMEOUT_MS. */
|
|
26
26
|
const DEFAULT_TIMEOUT_MS = 30000;
|
|
27
|
+
/**
|
|
28
|
+
* Conservative per-request limits for a *local* server.
|
|
29
|
+
*
|
|
30
|
+
* The self-hosted path is usually one CPU process holding one model, so a
|
|
31
|
+
* request's activations are the memory that matters. Keep requests small and
|
|
32
|
+
* let the batcher issue more of them; lower still with
|
|
33
|
+
* REPOSKEIN_EMBED_MAX_BATCH_ITEMS / _TOKENS.
|
|
34
|
+
*/
|
|
35
|
+
const DEFAULT_MAX_BATCH_ITEMS = 32;
|
|
36
|
+
const DEFAULT_MAX_BATCH_TOKENS = 8192;
|
|
27
37
|
export class HttpEmbeddingProvider {
|
|
28
38
|
_id = "http";
|
|
29
39
|
_url;
|
|
@@ -58,7 +68,10 @@ export class HttpEmbeddingProvider {
|
|
|
58
68
|
id() { return this._id; }
|
|
59
69
|
modelId() { return this._modelId; }
|
|
60
70
|
dims() { return this._dims; }
|
|
61
|
-
|
|
71
|
+
limits() {
|
|
72
|
+
return { maxItems: DEFAULT_MAX_BATCH_ITEMS, maxTokens: DEFAULT_MAX_BATCH_TOKENS };
|
|
73
|
+
}
|
|
74
|
+
async embedBatch(texts, kind) {
|
|
62
75
|
if (texts.length === 0)
|
|
63
76
|
return [];
|
|
64
77
|
const body = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/embed/providers/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,yFAAyF;AACzF,MAAM,kBAAkB,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/embed/providers/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* REPOSKEIN_EMBED_DIMS (optional; 256|512|1024|2048; default: 1024)
|
|
19
19
|
* VOYAGE_API_KEY (required)
|
|
20
20
|
*/
|
|
21
|
-
import type { EmbeddingProvider, EmbedKind } from "../provider.js";
|
|
21
|
+
import type { EmbeddingProvider, EmbedKind, BatchLimits } from "../provider.js";
|
|
22
22
|
export declare class VoyageEmbeddingProvider implements EmbeddingProvider {
|
|
23
23
|
private readonly _id;
|
|
24
24
|
private readonly _modelId;
|
|
@@ -31,5 +31,6 @@ export declare class VoyageEmbeddingProvider implements EmbeddingProvider {
|
|
|
31
31
|
id(): string;
|
|
32
32
|
modelId(): string;
|
|
33
33
|
dims(): number;
|
|
34
|
-
|
|
34
|
+
limits(): BatchLimits;
|
|
35
|
+
embedBatch(texts: string[], kind: EmbedKind): Promise<number[][]>;
|
|
35
36
|
}
|