@wrongstack/vector-memory 1.0.7 → 1.0.9
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/index.js +46 -10
- package/dist/store.d.ts +1 -1
- package/dist/types.d.ts +7 -0
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -378,8 +378,13 @@ function createSageSurfaceSyncSource(sage, opts = {}) {
|
|
|
378
378
|
const requested = limit === void 0 ? maxTotal : clamp(limit, 1, maxTotal === Number.POSITIVE_INFINITY ? limit : maxTotal);
|
|
379
379
|
const memories = [];
|
|
380
380
|
let cursor;
|
|
381
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
381
382
|
let noProgressPages = 0;
|
|
382
383
|
while (memories.length < requested) {
|
|
384
|
+
if (cursor !== void 0) {
|
|
385
|
+
if (seenCursors.has(cursor)) break;
|
|
386
|
+
seenCursors.add(cursor);
|
|
387
|
+
}
|
|
383
388
|
const remaining = requested - memories.length;
|
|
384
389
|
const page = await sage.listSagePage({
|
|
385
390
|
statuses: ["active"],
|
|
@@ -402,6 +407,7 @@ function createSageSurfaceSyncSource(sage, opts = {}) {
|
|
|
402
407
|
});
|
|
403
408
|
}
|
|
404
409
|
if (!page.nextCursor) break;
|
|
410
|
+
if (seenCursors.has(page.nextCursor)) break;
|
|
405
411
|
if (rows.length === 0) {
|
|
406
412
|
noProgressPages++;
|
|
407
413
|
if (noProgressPages > 3) break;
|
|
@@ -929,9 +935,9 @@ var VectorMemoryStore = class _VectorMemoryStore {
|
|
|
929
935
|
* Embed `text`, hitting the provider-level cache first. Cache miss falls
|
|
930
936
|
* through to the configured provider and writes the result back. Returns
|
|
931
937
|
* `undefined` when the provider fails — the caller can persist the entry
|
|
932
|
-
* without a vector (fail-open).
|
|
938
|
+
* without a vector (fail-open) — unless `strict`, which throws instead.
|
|
933
939
|
*/
|
|
934
|
-
async embedWithCache(text) {
|
|
940
|
+
async embedWithCache(text, strict = false) {
|
|
935
941
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
936
942
|
const cached = this.cachedVector(text, now);
|
|
937
943
|
if (cached) return cached;
|
|
@@ -940,7 +946,13 @@ var VectorMemoryStore = class _VectorMemoryStore {
|
|
|
940
946
|
const vec = result[0];
|
|
941
947
|
if (vec) this.cacheVector(text, vec, now);
|
|
942
948
|
return vec;
|
|
943
|
-
} catch {
|
|
949
|
+
} catch (err) {
|
|
950
|
+
if (strict) {
|
|
951
|
+
throw new VectorMemoryProviderUnavailableError(
|
|
952
|
+
`Embedding provider "${this.provider.id}" failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
953
|
+
err
|
|
954
|
+
);
|
|
955
|
+
}
|
|
944
956
|
return void 0;
|
|
945
957
|
}
|
|
946
958
|
}
|
|
@@ -1097,8 +1109,16 @@ var VectorMemoryStore = class _VectorMemoryStore {
|
|
|
1097
1109
|
const threshold = opts.threshold ?? 0;
|
|
1098
1110
|
const includeVectors = opts.includeVectors === true;
|
|
1099
1111
|
if (typeof query !== "string" || query.trim().length === 0) return [];
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1112
|
+
const strict = opts.failOnEmbeddingError === true;
|
|
1113
|
+
const queryVec = await this.embedWithCache(query, strict);
|
|
1114
|
+
if (!queryVec || queryVec.length === 0) {
|
|
1115
|
+
if (strict) {
|
|
1116
|
+
throw new VectorMemoryProviderUnavailableError(
|
|
1117
|
+
`Embedding provider "${this.provider.id}" returned no vector for the query.`
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
return [];
|
|
1121
|
+
}
|
|
1102
1122
|
const providerId = this.provider.id;
|
|
1103
1123
|
const dimensions = this.provider.dimensions;
|
|
1104
1124
|
const filters = ["v.provider_id = ?", "v.dimensions = ?"];
|
|
@@ -1421,7 +1441,7 @@ function vectorMemorySearchTool(store) {
|
|
|
1421
1441
|
return {
|
|
1422
1442
|
name: "vector_memory_search",
|
|
1423
1443
|
category: "Memory",
|
|
1424
|
-
description: "Semantic search over the vector memory store. Embeds the query with the active provider and returns the top-k entries ranked by cosine similarity.
|
|
1444
|
+
description: "Semantic search over the vector memory store. Embeds the query with the active provider and returns the top-k entries ranked by cosine similarity. Fails when the embedding provider is unavailable \u2014 fall back to lexical search (sage `memory_search`) in that case.",
|
|
1425
1445
|
usageHint: "Use when you want results ranked by meaning. Pairs well with sage `memory_search` for keyword precision.",
|
|
1426
1446
|
permission: "auto",
|
|
1427
1447
|
mutating: false,
|
|
@@ -1464,7 +1484,9 @@ function vectorMemorySearchTool(store) {
|
|
|
1464
1484
|
limit: input.limit !== void 0 ? input.limit : void 0,
|
|
1465
1485
|
threshold: input.threshold !== void 0 ? input.threshold : void 0,
|
|
1466
1486
|
scope: input.scope,
|
|
1467
|
-
kind: input.kind
|
|
1487
|
+
kind: input.kind,
|
|
1488
|
+
// An embedding outage must fail the call, not look like "no matches".
|
|
1489
|
+
failOnEmbeddingError: true
|
|
1468
1490
|
});
|
|
1469
1491
|
return {
|
|
1470
1492
|
hits: hits.map((h) => ({
|
|
@@ -1522,7 +1544,12 @@ function vectorMemoryForgetTool(store) {
|
|
|
1522
1544
|
required: ["id"],
|
|
1523
1545
|
additionalProperties: false
|
|
1524
1546
|
},
|
|
1525
|
-
execute: async (input) =>
|
|
1547
|
+
execute: async (input) => {
|
|
1548
|
+
if (!await store.forget(input.id)) {
|
|
1549
|
+
throw new Error(`vector_memory_forget: no entry with id "${input.id}".`);
|
|
1550
|
+
}
|
|
1551
|
+
return { removed: true };
|
|
1552
|
+
}
|
|
1526
1553
|
};
|
|
1527
1554
|
}
|
|
1528
1555
|
|
|
@@ -1547,7 +1574,8 @@ var TransformersEmbeddingProvider = class {
|
|
|
1547
1574
|
this.cacheDir = opts.cacheDir;
|
|
1548
1575
|
this.dtype = opts.dtype ?? DEFAULT_VECTOR_DTYPE;
|
|
1549
1576
|
this.device = opts.device ?? "cpu";
|
|
1550
|
-
|
|
1577
|
+
const batchSize = opts.batchSize ?? 16;
|
|
1578
|
+
this.batchSize = Number.isFinite(batchSize) && batchSize >= 1 ? Math.floor(batchSize) : 16;
|
|
1551
1579
|
this.maxChars = opts.maxChars ?? 2048;
|
|
1552
1580
|
this.allowRemote = opts.allowRemoteModels ?? true;
|
|
1553
1581
|
this.dimensions = DEFAULT_VECTOR_DIMENSIONS;
|
|
@@ -1595,7 +1623,15 @@ var TransformersEmbeddingProvider = class {
|
|
|
1595
1623
|
if (Array.isArray(nested) && Array.isArray(nested[0])) {
|
|
1596
1624
|
return nested.map((row) => Float32Array.from(row));
|
|
1597
1625
|
}
|
|
1598
|
-
|
|
1626
|
+
const flat2 = nested;
|
|
1627
|
+
if (batchSize > 1 && flat2.length > 0 && flat2.length % batchSize === 0) {
|
|
1628
|
+
const dimensions = flat2.length / batchSize;
|
|
1629
|
+
return Array.from(
|
|
1630
|
+
{ length: batchSize },
|
|
1631
|
+
(_, index) => Float32Array.from(flat2.slice(index * dimensions, (index + 1) * dimensions))
|
|
1632
|
+
);
|
|
1633
|
+
}
|
|
1634
|
+
return [Float32Array.from(flat2)];
|
|
1599
1635
|
}
|
|
1600
1636
|
const flat = out.data;
|
|
1601
1637
|
if (flat instanceof Float32Array) {
|
package/dist/store.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export declare class VectorMemoryStore {
|
|
|
37
37
|
* Embed `text`, hitting the provider-level cache first. Cache miss falls
|
|
38
38
|
* through to the configured provider and writes the result back. Returns
|
|
39
39
|
* `undefined` when the provider fails — the caller can persist the entry
|
|
40
|
-
* without a vector (fail-open).
|
|
40
|
+
* without a vector (fail-open) — unless `strict`, which throws instead.
|
|
41
41
|
*/
|
|
42
42
|
private embedWithCache;
|
|
43
43
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -55,6 +55,13 @@ export interface VectorSearchOptions {
|
|
|
55
55
|
* build the pairwise-similarity heatmap.
|
|
56
56
|
*/
|
|
57
57
|
includeVectors?: boolean | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* When true, a failed query embedding THROWS
|
|
60
|
+
* `VectorMemoryProviderUnavailableError` instead of returning `[]`. The
|
|
61
|
+
* default (fail-open) suits fusion callers; the agent tool sets it so an
|
|
62
|
+
* outage is not reported as "no matches".
|
|
63
|
+
*/
|
|
64
|
+
failOnEmbeddingError?: boolean | undefined;
|
|
58
65
|
}
|
|
59
66
|
export interface VectorSearchHit {
|
|
60
67
|
entry: VectorEntry;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/vector-memory",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "WrongStack Vector Memory — an additional vector-search memory store powered by @huggingface/transformers (local ONNX embeddings), alongside the SAGE lexical memory system.",
|
|
6
6
|
"repository": {
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"README.md"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@wrongstack/core": "1.0.
|
|
31
|
-
"@wrongstack/persistence": "1.0.
|
|
32
|
-
"@wrongstack/sage": "1.0.
|
|
30
|
+
"@wrongstack/core": "1.0.9",
|
|
31
|
+
"@wrongstack/persistence": "1.0.9",
|
|
32
|
+
"@wrongstack/sage": "1.0.9"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@types/node": "^26.
|
|
35
|
+
"@types/node": "^26.5.1",
|
|
36
36
|
"typescript": "^7.0.2",
|
|
37
|
-
"vitest": "^
|
|
37
|
+
"vitest": "^5.0.0"
|
|
38
38
|
},
|
|
39
39
|
"publishConfig": {
|
|
40
40
|
"access": "public",
|