@wiscale/velesdb-sdk 1.18.0 → 3.0.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 +126 -9
- package/dist/index.d.mts +243 -33
- package/dist/index.d.ts +243 -33
- package/dist/index.js +561 -58
- package/dist/index.mjs +554 -56
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -5,8 +5,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __esm = (fn, res) => function __init() {
|
|
9
|
-
|
|
8
|
+
var __esm = (fn, res, err) => function __init() {
|
|
9
|
+
if (err) throw err[0];
|
|
10
|
+
try {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw err = [e], e;
|
|
14
|
+
}
|
|
10
15
|
};
|
|
11
16
|
var __export = (target, all) => {
|
|
12
17
|
for (var name in all)
|
|
@@ -182,6 +187,7 @@ var REST_CAPABILITIES = Object.freeze({
|
|
|
182
187
|
graphTraversal: true,
|
|
183
188
|
secondaryIndexes: true,
|
|
184
189
|
agentMemory: true,
|
|
190
|
+
enableStreaming: true,
|
|
185
191
|
streamInsert: true,
|
|
186
192
|
pqTraining: true,
|
|
187
193
|
velesqlQuery: true,
|
|
@@ -197,9 +203,10 @@ var WASM_CAPABILITIES = Object.freeze({
|
|
|
197
203
|
graphTraversal: false,
|
|
198
204
|
secondaryIndexes: false,
|
|
199
205
|
agentMemory: false,
|
|
206
|
+
enableStreaming: false,
|
|
200
207
|
streamInsert: false,
|
|
201
208
|
pqTraining: false,
|
|
202
|
-
velesqlQuery:
|
|
209
|
+
velesqlQuery: false,
|
|
203
210
|
collectionIntrospection: false
|
|
204
211
|
});
|
|
205
212
|
|
|
@@ -437,20 +444,47 @@ async function wasmMultiQuerySearch(ctx, collectionName, vectors, options) {
|
|
|
437
444
|
);
|
|
438
445
|
return raw.map((r) => mapWasmResult(ctx, collection, r));
|
|
439
446
|
}
|
|
440
|
-
|
|
447
|
+
var PURE_NEAR_QUERY = /^\s*select\s+\*\s+from\s+([a-z_]\w*)\s+where\s+vector\s+near\s+\$([a-z_]\w*)\s*(?:limit\s+(\d+))?\s*;?\s*$/i;
|
|
448
|
+
function parsePureNearQuery(queryString) {
|
|
449
|
+
const match = PURE_NEAR_QUERY.exec(queryString);
|
|
450
|
+
if (!match) {
|
|
451
|
+
throw new VelesDBError(
|
|
452
|
+
`The WASM backend only executes pure top-k NEAR queries of the form "SELECT * FROM <collection> WHERE vector NEAR $param [LIMIT n]". WHERE predicates, JOIN, GROUP BY, MATCH, set operations and FUSION are not evaluated in WASM \u2014 use the REST backend (velesdb-server) for full VelesQL. Received: ${queryString}`,
|
|
453
|
+
"NOT_SUPPORTED"
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
const parsed = { from: match[1], param: match[2] };
|
|
457
|
+
if (match[3] !== void 0) {
|
|
458
|
+
parsed.limit = Number(match[3]);
|
|
459
|
+
}
|
|
460
|
+
return parsed;
|
|
461
|
+
}
|
|
462
|
+
function resolveQueryK(limit, requestedK) {
|
|
463
|
+
if (limit !== void 0) {
|
|
464
|
+
return limit;
|
|
465
|
+
}
|
|
466
|
+
return typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
|
|
467
|
+
}
|
|
468
|
+
async function wasmQuery(ctx, collectionName, queryString, params, _options) {
|
|
441
469
|
const collection = ctx.getCollection(collectionName);
|
|
442
470
|
if (!collection) {
|
|
443
471
|
throw new NotFoundError(`Collection '${collectionName}'`);
|
|
444
472
|
}
|
|
445
|
-
const
|
|
473
|
+
const parsed = parsePureNearQuery(queryString);
|
|
474
|
+
if (parsed.from !== collectionName) {
|
|
475
|
+
throw new VelesDBError(
|
|
476
|
+
`Query targets collection '${parsed.from}' but was executed against '${collectionName}'.`,
|
|
477
|
+
"BAD_REQUEST"
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
const paramsVector = params?.[parsed.param];
|
|
446
481
|
if (!Array.isArray(paramsVector) && !(paramsVector instanceof Float32Array)) {
|
|
447
482
|
throw new VelesDBError(
|
|
448
|
-
|
|
483
|
+
`WASM query() expects params.${parsed.param} to contain the query embedding vector.`,
|
|
449
484
|
"BAD_REQUEST"
|
|
450
485
|
);
|
|
451
486
|
}
|
|
452
|
-
const
|
|
453
|
-
const k = typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
|
|
487
|
+
const k = resolveQueryK(parsed.limit, params?.k);
|
|
454
488
|
const raw = collection.store.query(
|
|
455
489
|
paramsVector instanceof Float32Array ? paramsVector : new Float32Array(paramsVector),
|
|
456
490
|
k
|
|
@@ -864,6 +898,9 @@ function validateCollectionName(name) {
|
|
|
864
898
|
);
|
|
865
899
|
}
|
|
866
900
|
}
|
|
901
|
+
async function safeJsonParse(response) {
|
|
902
|
+
return response.json().catch(() => ({}));
|
|
903
|
+
}
|
|
867
904
|
function toNumberArray(v) {
|
|
868
905
|
return v instanceof Float32Array ? Array.from(v) : v;
|
|
869
906
|
}
|
|
@@ -917,12 +954,18 @@ async function wasmScroll(_collection, _request) {
|
|
|
917
954
|
async function wasmTrainPq(_collection, _options) {
|
|
918
955
|
wasmNotSupported("PQ training");
|
|
919
956
|
}
|
|
957
|
+
async function wasmEnableStreaming(_collection, _config) {
|
|
958
|
+
wasmNotSupported("Streaming enable");
|
|
959
|
+
}
|
|
920
960
|
async function wasmStreamInsert(_collection, _docs) {
|
|
921
961
|
wasmNotSupported("Streaming insert");
|
|
922
962
|
}
|
|
923
963
|
async function wasmStreamUpsertPoints(_collection, _docs) {
|
|
924
964
|
wasmNotSupported("Streaming batch upsert");
|
|
925
965
|
}
|
|
966
|
+
async function wasmUpsertBatchRaw(_collection, _docs) {
|
|
967
|
+
wasmNotSupported("Binary bulk upsert (upsertBatchRaw)");
|
|
968
|
+
}
|
|
926
969
|
async function wasmCreateGraphCollection(_name, _config) {
|
|
927
970
|
wasmNotSupported("Graph collections");
|
|
928
971
|
}
|
|
@@ -938,6 +981,9 @@ async function wasmGetCollectionConfig(_collection) {
|
|
|
938
981
|
async function wasmSearchIds(_collection, _query, _options) {
|
|
939
982
|
wasmNotSupported("searchIds");
|
|
940
983
|
}
|
|
984
|
+
async function wasmMultiQuerySearchIds(_collection, _vectors, _options) {
|
|
985
|
+
wasmNotSupported("multiQuerySearchIds");
|
|
986
|
+
}
|
|
941
987
|
async function wasmStoreSemanticFact(_collection, _entry) {
|
|
942
988
|
wasmNotSupported("Agent memory");
|
|
943
989
|
}
|
|
@@ -950,6 +996,12 @@ async function wasmRecordEpisodicEvent(_collection, _event) {
|
|
|
950
996
|
async function wasmRecallEpisodicEvents(_collection, _embedding, _k) {
|
|
951
997
|
wasmNotSupported("Agent memory");
|
|
952
998
|
}
|
|
999
|
+
async function wasmRecallRecentEvents(_collection, _since) {
|
|
1000
|
+
wasmNotSupported("Agent memory");
|
|
1001
|
+
}
|
|
1002
|
+
async function wasmRecallOlderThanEvents(_collection, _before) {
|
|
1003
|
+
wasmNotSupported("Agent memory");
|
|
1004
|
+
}
|
|
953
1005
|
async function wasmStoreProceduralPattern(_collection, _pattern) {
|
|
954
1006
|
wasmNotSupported("Agent memory");
|
|
955
1007
|
}
|
|
@@ -997,6 +1049,18 @@ function wasmUpsertNodePayload(_c, _id, _p) {
|
|
|
997
1049
|
function wasmGraphSearch(_c, _r) {
|
|
998
1050
|
return Promise.resolve(wasmNotSupported("Graph search"));
|
|
999
1051
|
}
|
|
1052
|
+
function wasmRelate(_c, _req) {
|
|
1053
|
+
return Promise.resolve(wasmNotSupported("Relation edges"));
|
|
1054
|
+
}
|
|
1055
|
+
function wasmUnrelate(_c, _id) {
|
|
1056
|
+
return Promise.resolve(wasmNotSupported("Relation edge removal"));
|
|
1057
|
+
}
|
|
1058
|
+
function wasmGetRelations(_c, _id) {
|
|
1059
|
+
return Promise.resolve(wasmNotSupported("Relation edges"));
|
|
1060
|
+
}
|
|
1061
|
+
function wasmSetTtlDurable(_c, _id, _ttl) {
|
|
1062
|
+
return Promise.resolve(wasmNotSupported("Durable TTL"));
|
|
1063
|
+
}
|
|
1000
1064
|
|
|
1001
1065
|
// src/backends/wasm.ts
|
|
1002
1066
|
var WasmBackend = class {
|
|
@@ -1176,6 +1240,9 @@ var WasmBackend = class {
|
|
|
1176
1240
|
}
|
|
1177
1241
|
}
|
|
1178
1242
|
}
|
|
1243
|
+
async upsertBatchRaw(c, d) {
|
|
1244
|
+
return wasmUpsertBatchRaw(c, d);
|
|
1245
|
+
}
|
|
1179
1246
|
async delete(collectionName, id) {
|
|
1180
1247
|
this.ensureInitialized();
|
|
1181
1248
|
const collection = this.collections.get(collectionName);
|
|
@@ -1307,6 +1374,10 @@ var WasmBackend = class {
|
|
|
1307
1374
|
this.ensureInitialized();
|
|
1308
1375
|
return wasmTrainPq(c, o);
|
|
1309
1376
|
}
|
|
1377
|
+
async enableStreaming(c, cfg) {
|
|
1378
|
+
this.ensureInitialized();
|
|
1379
|
+
return wasmEnableStreaming(c, cfg);
|
|
1380
|
+
}
|
|
1310
1381
|
async streamInsert(c, d) {
|
|
1311
1382
|
this.ensureInitialized();
|
|
1312
1383
|
return wasmStreamInsert(c, d);
|
|
@@ -1335,6 +1406,10 @@ var WasmBackend = class {
|
|
|
1335
1406
|
this.ensureInitialized();
|
|
1336
1407
|
return wasmSearchIds(c, q, o);
|
|
1337
1408
|
}
|
|
1409
|
+
async multiQuerySearchIds(c, v, o) {
|
|
1410
|
+
this.ensureInitialized();
|
|
1411
|
+
return wasmMultiQuerySearchIds(c, v, o);
|
|
1412
|
+
}
|
|
1338
1413
|
async storeSemanticFact(c, e) {
|
|
1339
1414
|
this.ensureInitialized();
|
|
1340
1415
|
return wasmStoreSemanticFact(c, e);
|
|
@@ -1351,6 +1426,14 @@ var WasmBackend = class {
|
|
|
1351
1426
|
this.ensureInitialized();
|
|
1352
1427
|
return wasmRecallEpisodicEvents(c, e, k);
|
|
1353
1428
|
}
|
|
1429
|
+
async recallRecentEvents(c, since) {
|
|
1430
|
+
this.ensureInitialized();
|
|
1431
|
+
return wasmRecallRecentEvents(c, since);
|
|
1432
|
+
}
|
|
1433
|
+
async recallOlderThanEvents(c, before) {
|
|
1434
|
+
this.ensureInitialized();
|
|
1435
|
+
return wasmRecallOlderThanEvents(c, before);
|
|
1436
|
+
}
|
|
1354
1437
|
async storeProceduralPattern(c, p) {
|
|
1355
1438
|
this.ensureInitialized();
|
|
1356
1439
|
return wasmStoreProceduralPattern(c, p);
|
|
@@ -1412,16 +1495,46 @@ var WasmBackend = class {
|
|
|
1412
1495
|
this.ensureInitialized();
|
|
1413
1496
|
return wasmSparseSearchNamed(c, q, idx, o);
|
|
1414
1497
|
}
|
|
1498
|
+
async relate(c, req) {
|
|
1499
|
+
this.ensureInitialized();
|
|
1500
|
+
return wasmRelate(c, req);
|
|
1501
|
+
}
|
|
1502
|
+
async unrelate(c, edgeId) {
|
|
1503
|
+
this.ensureInitialized();
|
|
1504
|
+
return wasmUnrelate(c, edgeId);
|
|
1505
|
+
}
|
|
1506
|
+
async getRelations(c, pointId) {
|
|
1507
|
+
this.ensureInitialized();
|
|
1508
|
+
return wasmGetRelations(c, pointId);
|
|
1509
|
+
}
|
|
1510
|
+
async setTtlDurable(c, pointId, ttlSeconds) {
|
|
1511
|
+
this.ensureInitialized();
|
|
1512
|
+
return wasmSetTtlDurable(c, pointId, ttlSeconds);
|
|
1513
|
+
}
|
|
1415
1514
|
};
|
|
1416
1515
|
|
|
1417
1516
|
// src/backends/crud-backend.ts
|
|
1517
|
+
var RAW_BULK_HEADER_LEN = 16;
|
|
1518
|
+
var RAW_BULK_MAGIC = [86, 82, 66, 49];
|
|
1519
|
+
var RAW_BULK_ID_WIDTH = 8;
|
|
1520
|
+
var U64_MAX = 18446744073709551615n;
|
|
1521
|
+
function coerceDecimalStringId(id) {
|
|
1522
|
+
if (!/^\d+$/.test(id)) return NaN;
|
|
1523
|
+
const big = BigInt(id);
|
|
1524
|
+
if (big > U64_MAX) return NaN;
|
|
1525
|
+
return big > BigInt(Number.MAX_SAFE_INTEGER) ? id : Number(id);
|
|
1526
|
+
}
|
|
1418
1527
|
function parseRestPointId(id) {
|
|
1419
|
-
|
|
1528
|
+
const coerced = typeof id === "string" ? coerceDecimalStringId(id) : id;
|
|
1529
|
+
if (typeof coerced === "string") {
|
|
1530
|
+
return coerced;
|
|
1531
|
+
}
|
|
1532
|
+
if (!Number.isFinite(coerced) || coerced < 0 || !Number.isInteger(coerced) || coerced > Number.MAX_SAFE_INTEGER) {
|
|
1420
1533
|
throw new ValidationError(
|
|
1421
|
-
`REST backend requires numeric u64-compatible IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER}). Received: ${String(id)}`
|
|
1534
|
+
`REST backend requires numeric u64-compatible IDs: a non-negative integer in the JS safe integer range (0..${Number.MAX_SAFE_INTEGER}) or a decimal string up to u64::MAX (${U64_MAX}). Received: ${String(id)}`
|
|
1422
1535
|
);
|
|
1423
1536
|
}
|
|
1424
|
-
return
|
|
1537
|
+
return coerced;
|
|
1425
1538
|
}
|
|
1426
1539
|
function sparseVectorToRestFormat(sv) {
|
|
1427
1540
|
const result = {};
|
|
@@ -1554,6 +1667,105 @@ async function flush(transport, collection) {
|
|
|
1554
1667
|
);
|
|
1555
1668
|
throwOnError(response, `Collection '${collection}'`);
|
|
1556
1669
|
}
|
|
1670
|
+
function encodeRawBulk(ids, vectors, dim) {
|
|
1671
|
+
const count = ids.length;
|
|
1672
|
+
if (vectors.length !== count) {
|
|
1673
|
+
throw new ValidationError(
|
|
1674
|
+
`encodeRawBulk: ids length (${count}) must match vectors length (${vectors.length})`
|
|
1675
|
+
);
|
|
1676
|
+
}
|
|
1677
|
+
const buf = new Uint8Array(RAW_BULK_HEADER_LEN + count * 8 + count * dim * 4);
|
|
1678
|
+
const view = new DataView(buf.buffer);
|
|
1679
|
+
buf.set(RAW_BULK_MAGIC, 0);
|
|
1680
|
+
view.setUint32(4, count, true);
|
|
1681
|
+
view.setUint32(8, dim, true);
|
|
1682
|
+
buf[12] = RAW_BULK_ID_WIDTH;
|
|
1683
|
+
writeIds(view, ids);
|
|
1684
|
+
writeVectors(view, vectors, dim, count);
|
|
1685
|
+
return buf;
|
|
1686
|
+
}
|
|
1687
|
+
function writeIds(view, ids) {
|
|
1688
|
+
let off = RAW_BULK_HEADER_LEN;
|
|
1689
|
+
for (const id of ids) {
|
|
1690
|
+
view.setBigUint64(off, BigInt(id), true);
|
|
1691
|
+
off += 8;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
function writeVectors(view, vectors, dim, count) {
|
|
1695
|
+
let off = RAW_BULK_HEADER_LEN + count * 8;
|
|
1696
|
+
for (const vec of vectors) {
|
|
1697
|
+
if (vec.length !== dim) {
|
|
1698
|
+
throw new ValidationError(
|
|
1699
|
+
`encodeRawBulk: vector length (${vec.length}) must match dim (${dim})`
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
for (let i = 0; i < dim; i++) {
|
|
1703
|
+
view.setFloat32(off, vec[i] ?? 0, true);
|
|
1704
|
+
off += 4;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
async function upsertBatchRaw(transport, collection, docs, dim) {
|
|
1709
|
+
const ids = docs.map((d) => coerceNumericId(d.id));
|
|
1710
|
+
const vectors = docs.map((d) => d.vector);
|
|
1711
|
+
const body = encodeRawBulk(ids, vectors, dim);
|
|
1712
|
+
return sendRawBulk(transport, collection, body);
|
|
1713
|
+
}
|
|
1714
|
+
function coerceNumericId(id) {
|
|
1715
|
+
const parsed = parseRestPointId(id);
|
|
1716
|
+
if (typeof parsed === "string") {
|
|
1717
|
+
throw new ValidationError(
|
|
1718
|
+
`upsertBatchRaw requires ids in the JS safe integer range; received: ${parsed}`
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
return parsed;
|
|
1722
|
+
}
|
|
1723
|
+
async function sendRawBulk(transport, collection, body) {
|
|
1724
|
+
const url = `${transport.baseUrl}${collectionPath(collection)}/points/raw`;
|
|
1725
|
+
const headers = {
|
|
1726
|
+
"Content-Type": "application/octet-stream"
|
|
1727
|
+
};
|
|
1728
|
+
if (transport.apiKey) {
|
|
1729
|
+
headers["Authorization"] = `Bearer ${transport.apiKey}`;
|
|
1730
|
+
}
|
|
1731
|
+
const controller = new AbortController();
|
|
1732
|
+
const timeoutId = setTimeout(() => controller.abort(), transport.timeout);
|
|
1733
|
+
try {
|
|
1734
|
+
const response = await fetch(url, {
|
|
1735
|
+
method: "POST",
|
|
1736
|
+
headers,
|
|
1737
|
+
body,
|
|
1738
|
+
signal: controller.signal
|
|
1739
|
+
});
|
|
1740
|
+
clearTimeout(timeoutId);
|
|
1741
|
+
return await parseRawBulkResponse(response);
|
|
1742
|
+
} catch (error) {
|
|
1743
|
+
clearTimeout(timeoutId);
|
|
1744
|
+
throw wrapRawBulkError(error);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
async function parseRawBulkResponse(response) {
|
|
1748
|
+
const data = await safeJsonParse(response);
|
|
1749
|
+
if (!response.ok) {
|
|
1750
|
+
const code = typeof data.code === "string" ? data.code : `HTTP_${response.status}`;
|
|
1751
|
+
const message = typeof data.error === "string" ? data.error : `HTTP ${response.status}`;
|
|
1752
|
+
throw new VelesDBError(message, code);
|
|
1753
|
+
}
|
|
1754
|
+
return typeof data.count === "number" ? data.count : 0;
|
|
1755
|
+
}
|
|
1756
|
+
function wrapRawBulkError(error) {
|
|
1757
|
+
if (error instanceof VelesDBError) {
|
|
1758
|
+
return error;
|
|
1759
|
+
}
|
|
1760
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
1761
|
+
return new ConnectionError("Request timeout");
|
|
1762
|
+
}
|
|
1763
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1764
|
+
return new ConnectionError(
|
|
1765
|
+
`Raw bulk upsert failed: ${message}`,
|
|
1766
|
+
error instanceof Error ? error : void 0
|
|
1767
|
+
);
|
|
1768
|
+
}
|
|
1557
1769
|
|
|
1558
1770
|
// src/backends/rest-http.ts
|
|
1559
1771
|
var STATUS_ERROR_CODES = {
|
|
@@ -1624,7 +1836,7 @@ async function request(config, method, path, body) {
|
|
|
1624
1836
|
signal: controller.signal
|
|
1625
1837
|
});
|
|
1626
1838
|
clearTimeout(timeoutId);
|
|
1627
|
-
const data = await response
|
|
1839
|
+
const data = await safeJsonParse(response);
|
|
1628
1840
|
if (!response.ok) {
|
|
1629
1841
|
const ep = extractErrorPayload(data);
|
|
1630
1842
|
return { error: {
|
|
@@ -1648,6 +1860,13 @@ function buildCrudTransport(config) {
|
|
|
1648
1860
|
requestJson: (m, p, b) => request(config, m, p, b)
|
|
1649
1861
|
};
|
|
1650
1862
|
}
|
|
1863
|
+
function buildRawBulkTransport(config) {
|
|
1864
|
+
return {
|
|
1865
|
+
baseUrl: config.baseUrl,
|
|
1866
|
+
apiKey: config.apiKey,
|
|
1867
|
+
timeout: config.timeout
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1651
1870
|
function buildSearchTransport(config) {
|
|
1652
1871
|
return {
|
|
1653
1872
|
requestJson: (m, p, b) => request(config, m, p, b),
|
|
@@ -1876,6 +2095,31 @@ async function graphSearch(transport, collection, request2) {
|
|
|
1876
2095
|
return { results: items };
|
|
1877
2096
|
}
|
|
1878
2097
|
|
|
2098
|
+
// src/backends/scroll-backend.ts
|
|
2099
|
+
async function scroll(transport, collection, request2) {
|
|
2100
|
+
const body = {};
|
|
2101
|
+
if (request2?.cursor !== void 0) {
|
|
2102
|
+
body.cursor = request2.cursor;
|
|
2103
|
+
}
|
|
2104
|
+
if (request2?.batchSize !== void 0) {
|
|
2105
|
+
body.batch_size = request2.batchSize;
|
|
2106
|
+
}
|
|
2107
|
+
if (request2?.filter !== void 0) {
|
|
2108
|
+
body.filter = request2.filter;
|
|
2109
|
+
}
|
|
2110
|
+
const response = await transport.requestJson(
|
|
2111
|
+
"POST",
|
|
2112
|
+
`${collectionPath(collection)}/points/scroll`,
|
|
2113
|
+
body
|
|
2114
|
+
);
|
|
2115
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2116
|
+
const data = response.data;
|
|
2117
|
+
return {
|
|
2118
|
+
points: data.points,
|
|
2119
|
+
nextCursor: data.next_cursor
|
|
2120
|
+
};
|
|
2121
|
+
}
|
|
2122
|
+
|
|
1879
2123
|
// src/backends/agent-memory-backend.ts
|
|
1880
2124
|
var _idCounter = 0;
|
|
1881
2125
|
var _lastTimestamp = 0;
|
|
@@ -1893,20 +2137,28 @@ function generateUniqueId() {
|
|
|
1893
2137
|
}
|
|
1894
2138
|
return _lastTimestamp * 1e3 + _idCounter;
|
|
1895
2139
|
}
|
|
2140
|
+
function memoryIdToString(id) {
|
|
2141
|
+
return String(id);
|
|
2142
|
+
}
|
|
2143
|
+
function nowUnixSeconds() {
|
|
2144
|
+
return Math.floor(Date.now() / 1e3);
|
|
2145
|
+
}
|
|
1896
2146
|
async function storeSemanticFact(transport, collection, entry) {
|
|
1897
2147
|
const response = await transport.requestJson(
|
|
1898
2148
|
"POST",
|
|
1899
2149
|
`${collectionPath(collection)}/points`,
|
|
1900
2150
|
{
|
|
1901
2151
|
points: [{
|
|
1902
|
-
id: entry.id,
|
|
2152
|
+
id: parseRestPointId(entry.id),
|
|
1903
2153
|
vector: entry.embedding,
|
|
1904
2154
|
payload: {
|
|
1905
2155
|
// Caller metadata is spread first so the reserved keys below
|
|
1906
|
-
// (`_memory_type`, `
|
|
2156
|
+
// (`_memory_type`, `content`) always win and cannot be clobbered.
|
|
1907
2157
|
...entry.metadata,
|
|
1908
2158
|
_memory_type: "semantic",
|
|
1909
|
-
|
|
2159
|
+
// `content` matches the core semantic store and the server/Python
|
|
2160
|
+
// payload field (BREAKING: was `text` before this change).
|
|
2161
|
+
content: entry.text
|
|
1910
2162
|
}
|
|
1911
2163
|
}]
|
|
1912
2164
|
}
|
|
@@ -1917,7 +2169,8 @@ async function searchSemanticMemory(transport, collection, embedding, k = 5) {
|
|
|
1917
2169
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "semantic" });
|
|
1918
2170
|
}
|
|
1919
2171
|
async function recordEpisodicEvent(transport, collection, event) {
|
|
1920
|
-
const id = generateUniqueId();
|
|
2172
|
+
const id = event.id !== void 0 ? parseRestPointId(event.id) : generateUniqueId();
|
|
2173
|
+
const timestamp = event.timestamp ?? nowUnixSeconds();
|
|
1921
2174
|
const response = await transport.requestJson(
|
|
1922
2175
|
"POST",
|
|
1923
2176
|
`${collectionPath(collection)}/points`,
|
|
@@ -1933,19 +2186,21 @@ async function recordEpisodicEvent(transport, collection, event) {
|
|
|
1933
2186
|
...event.metadata,
|
|
1934
2187
|
_memory_type: "episodic",
|
|
1935
2188
|
event_type: event.eventType,
|
|
1936
|
-
|
|
2189
|
+
// NUMERIC unix-seconds, mirroring the core episodic store so
|
|
2190
|
+
// recallRecent/recallOlderThan can range-filter on it.
|
|
2191
|
+
timestamp
|
|
1937
2192
|
}
|
|
1938
2193
|
}]
|
|
1939
2194
|
}
|
|
1940
2195
|
);
|
|
1941
2196
|
throwOnError(response);
|
|
1942
|
-
return id;
|
|
2197
|
+
return memoryIdToString(id);
|
|
1943
2198
|
}
|
|
1944
2199
|
async function recallEpisodicEvents(transport, collection, embedding, k = 5) {
|
|
1945
2200
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "episodic" });
|
|
1946
2201
|
}
|
|
1947
2202
|
async function storeProceduralPattern(transport, collection, pattern) {
|
|
1948
|
-
const id = generateUniqueId();
|
|
2203
|
+
const id = pattern.id !== void 0 ? parseRestPointId(pattern.id) : generateUniqueId();
|
|
1949
2204
|
const response = await transport.requestJson(
|
|
1950
2205
|
"POST",
|
|
1951
2206
|
`${collectionPath(collection)}/points`,
|
|
@@ -1966,11 +2221,41 @@ async function storeProceduralPattern(transport, collection, pattern) {
|
|
|
1966
2221
|
}
|
|
1967
2222
|
);
|
|
1968
2223
|
throwOnError(response);
|
|
1969
|
-
return id;
|
|
2224
|
+
return memoryIdToString(id);
|
|
1970
2225
|
}
|
|
1971
2226
|
async function matchProceduralPatterns(transport, collection, embedding, k = 5) {
|
|
1972
2227
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "procedural" });
|
|
1973
2228
|
}
|
|
2229
|
+
function toEpisodicRecord(point) {
|
|
2230
|
+
const payload = point.payload ?? {};
|
|
2231
|
+
if (payload._memory_type !== "episodic") return void 0;
|
|
2232
|
+
if (typeof payload.timestamp !== "number") return void 0;
|
|
2233
|
+
return { id: String(point.id), timestamp: payload.timestamp, payload };
|
|
2234
|
+
}
|
|
2235
|
+
async function scrollEpisodicRecords(transport, collection) {
|
|
2236
|
+
const records = [];
|
|
2237
|
+
let cursor = null;
|
|
2238
|
+
do {
|
|
2239
|
+
const page = await scroll(transport, collection, {
|
|
2240
|
+
cursor: cursor ?? void 0,
|
|
2241
|
+
filter: { _memory_type: "episodic" }
|
|
2242
|
+
});
|
|
2243
|
+
for (const point of page.points) {
|
|
2244
|
+
const record = toEpisodicRecord(point);
|
|
2245
|
+
if (record !== void 0) records.push(record);
|
|
2246
|
+
}
|
|
2247
|
+
cursor = page.nextCursor;
|
|
2248
|
+
} while (cursor !== null && cursor !== void 0);
|
|
2249
|
+
return records;
|
|
2250
|
+
}
|
|
2251
|
+
async function recallRecentEvents(transport, collection, since) {
|
|
2252
|
+
const records = await scrollEpisodicRecords(transport, collection);
|
|
2253
|
+
return records.filter((r) => since === void 0 || r.timestamp >= since).sort((a, b) => b.timestamp - a.timestamp);
|
|
2254
|
+
}
|
|
2255
|
+
async function recallOlderThanEvents(transport, collection, before) {
|
|
2256
|
+
const records = await scrollEpisodicRecords(transport, collection);
|
|
2257
|
+
return records.filter((r) => r.timestamp < before).sort((a, b) => b.timestamp - a.timestamp);
|
|
2258
|
+
}
|
|
1974
2259
|
|
|
1975
2260
|
// src/search-quality.ts
|
|
1976
2261
|
function searchQualityToMode(quality) {
|
|
@@ -2069,6 +2354,22 @@ async function multiQuerySearch(transport, collection, vectors, options) {
|
|
|
2069
2354
|
throwOnError(response, `Collection '${collection}'`);
|
|
2070
2355
|
return response.data?.results ?? [];
|
|
2071
2356
|
}
|
|
2357
|
+
async function multiQuerySearchIds(transport, collection, vectors, options) {
|
|
2358
|
+
const formattedVectors = vectors.map(toNumberArray);
|
|
2359
|
+
const response = await transport.requestJson("POST", `${collectionPath(collection)}/search/multi/ids`, {
|
|
2360
|
+
vectors: formattedVectors,
|
|
2361
|
+
top_k: options?.k ?? 10,
|
|
2362
|
+
strategy: options?.fusion ?? "rrf",
|
|
2363
|
+
rrf_k: options?.fusionParams?.k ?? 60,
|
|
2364
|
+
avg_weight: options?.fusionParams?.avgWeight,
|
|
2365
|
+
max_weight: options?.fusionParams?.maxWeight,
|
|
2366
|
+
hit_weight: options?.fusionParams?.hitWeight,
|
|
2367
|
+
dense_weight: options?.fusionParams?.denseWeight,
|
|
2368
|
+
sparse_weight: options?.fusionParams?.sparseWeight
|
|
2369
|
+
});
|
|
2370
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2371
|
+
return response.data?.results ?? [];
|
|
2372
|
+
}
|
|
2072
2373
|
async function sparseSearchNamed(transport, collection, query3, indexName, options) {
|
|
2073
2374
|
const body = {
|
|
2074
2375
|
sparse_vectors: { [indexName]: transport.sparseToRest(query3) },
|
|
@@ -2203,6 +2504,64 @@ async function traverseParallel(transport, collection, request2) {
|
|
|
2203
2504
|
throwOnError(response, `Collection '${collection}'`);
|
|
2204
2505
|
return toTraverseResponse(response.data);
|
|
2205
2506
|
}
|
|
2507
|
+
async function relate(transport, collection, req) {
|
|
2508
|
+
const response = await transport.requestJson(
|
|
2509
|
+
"POST",
|
|
2510
|
+
`${collectionPath(collection)}/relations`,
|
|
2511
|
+
{
|
|
2512
|
+
source: req.source,
|
|
2513
|
+
target: req.target,
|
|
2514
|
+
rel_type: req.relType,
|
|
2515
|
+
properties: req.properties ?? {}
|
|
2516
|
+
}
|
|
2517
|
+
);
|
|
2518
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2519
|
+
return { edgeId: response.data.edge_id };
|
|
2520
|
+
}
|
|
2521
|
+
async function unrelate(transport, collection, edgeId) {
|
|
2522
|
+
const response = await transport.requestJson(
|
|
2523
|
+
"DELETE",
|
|
2524
|
+
`${collectionPath(collection)}/relations/${encodeURIComponent(String(edgeId))}`
|
|
2525
|
+
);
|
|
2526
|
+
if (response.error !== void 0) {
|
|
2527
|
+
const { code, message } = response.error;
|
|
2528
|
+
const err = parseVelesError(code, message);
|
|
2529
|
+
if (err instanceof EdgeNotFoundError) {
|
|
2530
|
+
return false;
|
|
2531
|
+
}
|
|
2532
|
+
if (code === "NOT_FOUND") {
|
|
2533
|
+
return false;
|
|
2534
|
+
}
|
|
2535
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2536
|
+
}
|
|
2537
|
+
return true;
|
|
2538
|
+
}
|
|
2539
|
+
async function getRelations(transport, collection, pointId) {
|
|
2540
|
+
const response = await transport.requestJson(
|
|
2541
|
+
"GET",
|
|
2542
|
+
`${collectionPath(collection)}/points/${encodeURIComponent(String(pointId))}/relations`
|
|
2543
|
+
);
|
|
2544
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2545
|
+
const raw = response.data;
|
|
2546
|
+
return {
|
|
2547
|
+
edges: raw.edges.map((e) => ({
|
|
2548
|
+
id: e.id,
|
|
2549
|
+
source: e.source,
|
|
2550
|
+
target: e.target,
|
|
2551
|
+
relType: e.rel_type,
|
|
2552
|
+
properties: e.properties
|
|
2553
|
+
})),
|
|
2554
|
+
count: raw.count
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
async function setTtlDurable(transport, collection, pointId, ttlSeconds) {
|
|
2558
|
+
const response = await transport.requestJson(
|
|
2559
|
+
"PATCH",
|
|
2560
|
+
`${collectionPath(collection)}/points/${encodeURIComponent(String(pointId))}/ttl`,
|
|
2561
|
+
{ ttl_seconds: ttlSeconds }
|
|
2562
|
+
);
|
|
2563
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2564
|
+
}
|
|
2206
2565
|
|
|
2207
2566
|
// src/backends/query-backend.ts
|
|
2208
2567
|
function isLikelyAggregationQuery(queryString) {
|
|
@@ -2228,7 +2587,7 @@ async function query(transport, collection, queryString, params, options) {
|
|
|
2228
2587
|
);
|
|
2229
2588
|
throwOnError(response, `Collection '${collection}'`);
|
|
2230
2589
|
const rawData = response.data;
|
|
2231
|
-
if (rawData && Object.prototype.hasOwnProperty.call(rawData, "result")) {
|
|
2590
|
+
if (rawData != null && Object.prototype.hasOwnProperty.call(rawData, "result")) {
|
|
2232
2591
|
return {
|
|
2233
2592
|
result: rawData.result,
|
|
2234
2593
|
stats: {
|
|
@@ -2335,31 +2694,6 @@ async function collectionSanity(transport, collection) {
|
|
|
2335
2694
|
};
|
|
2336
2695
|
}
|
|
2337
2696
|
|
|
2338
|
-
// src/backends/scroll-backend.ts
|
|
2339
|
-
async function scroll(transport, collection, request2) {
|
|
2340
|
-
const body = {};
|
|
2341
|
-
if (request2?.cursor !== void 0) {
|
|
2342
|
-
body.cursor = request2.cursor;
|
|
2343
|
-
}
|
|
2344
|
-
if (request2?.batchSize !== void 0) {
|
|
2345
|
-
body.batch_size = request2.batchSize;
|
|
2346
|
-
}
|
|
2347
|
-
if (request2?.filter !== void 0) {
|
|
2348
|
-
body.filter = request2.filter;
|
|
2349
|
-
}
|
|
2350
|
-
const response = await transport.requestJson(
|
|
2351
|
-
"POST",
|
|
2352
|
-
`${collectionPath(collection)}/points/scroll`,
|
|
2353
|
-
body
|
|
2354
|
-
);
|
|
2355
|
-
throwOnError(response, `Collection '${collection}'`);
|
|
2356
|
-
const data = response.data;
|
|
2357
|
-
return {
|
|
2358
|
-
points: data.points,
|
|
2359
|
-
nextCursor: data.next_cursor
|
|
2360
|
-
};
|
|
2361
|
-
}
|
|
2362
|
-
|
|
2363
2697
|
// src/backends/admin-backend.ts
|
|
2364
2698
|
function mapStatsResponse(data) {
|
|
2365
2699
|
let columnStats;
|
|
@@ -2523,7 +2857,7 @@ async function streamInsert(transport, collection, docs) {
|
|
|
2523
2857
|
throw new BackpressureError();
|
|
2524
2858
|
}
|
|
2525
2859
|
if (!response.ok && response.status !== 202) {
|
|
2526
|
-
const data = await response
|
|
2860
|
+
const data = await safeJsonParse(response);
|
|
2527
2861
|
const errorPayload = transport.extractErrorPayload(data);
|
|
2528
2862
|
throw new VelesDBError(
|
|
2529
2863
|
errorPayload.message ?? `HTTP ${response.status}`,
|
|
@@ -2545,9 +2879,35 @@ async function streamInsert(transport, collection, docs) {
|
|
|
2545
2879
|
}
|
|
2546
2880
|
}
|
|
2547
2881
|
}
|
|
2882
|
+
async function enableStreaming(transport, collection, config) {
|
|
2883
|
+
const body = {};
|
|
2884
|
+
if (config?.bufferSize !== void 0) {
|
|
2885
|
+
body.buffer_size = config.bufferSize;
|
|
2886
|
+
}
|
|
2887
|
+
if (config?.batchSize !== void 0) {
|
|
2888
|
+
body.batch_size = config.batchSize;
|
|
2889
|
+
}
|
|
2890
|
+
if (config?.flushIntervalMs !== void 0) {
|
|
2891
|
+
body.flush_interval_ms = config.flushIntervalMs;
|
|
2892
|
+
}
|
|
2893
|
+
const response = await transport.requestJson(
|
|
2894
|
+
"POST",
|
|
2895
|
+
`${collectionPath(collection)}/stream/enable`,
|
|
2896
|
+
body
|
|
2897
|
+
);
|
|
2898
|
+
throwOnError(response);
|
|
2899
|
+
}
|
|
2900
|
+
function requireSafeRangeId(restId) {
|
|
2901
|
+
if (typeof restId === "string") {
|
|
2902
|
+
throw new ValidationError(
|
|
2903
|
+
`streamUpsertPoints requires ids in the JS safe integer range (0..${Number.MAX_SAFE_INTEGER}); use upsert/upsertBatch for string ids above it. Received: ${restId}`
|
|
2904
|
+
);
|
|
2905
|
+
}
|
|
2906
|
+
return restId;
|
|
2907
|
+
}
|
|
2548
2908
|
async function streamUpsertPoints(transport, collection, docs) {
|
|
2549
2909
|
const ndjsonLines = docs.map((doc) => {
|
|
2550
|
-
const restId = transport.parseRestPointId(doc.id);
|
|
2910
|
+
const restId = requireSafeRangeId(transport.parseRestPointId(doc.id));
|
|
2551
2911
|
const vector = toNumberArray(doc.vector);
|
|
2552
2912
|
const point = {
|
|
2553
2913
|
id: restId,
|
|
@@ -2581,14 +2941,14 @@ async function streamUpsertPoints(transport, collection, docs) {
|
|
|
2581
2941
|
throw new BackpressureError();
|
|
2582
2942
|
}
|
|
2583
2943
|
if (!response.ok) {
|
|
2584
|
-
const data2 = await response
|
|
2944
|
+
const data2 = await safeJsonParse(response);
|
|
2585
2945
|
const errorPayload = transport.extractErrorPayload(data2);
|
|
2586
2946
|
throw new VelesDBError(
|
|
2587
2947
|
errorPayload.message ?? `HTTP ${response.status}`,
|
|
2588
2948
|
errorPayload.code ?? transport.mapStatusToErrorCode(response.status)
|
|
2589
2949
|
);
|
|
2590
2950
|
}
|
|
2591
|
-
const data = await response
|
|
2951
|
+
const data = await safeJsonParse(response);
|
|
2592
2952
|
return {
|
|
2593
2953
|
message: typeof data.message === "string" ? data.message : "Stream processed",
|
|
2594
2954
|
inserted: typeof data.inserted === "number" ? data.inserted : 0,
|
|
@@ -2673,6 +3033,10 @@ var RestBackend = class {
|
|
|
2673
3033
|
this.ensureInitialized();
|
|
2674
3034
|
return upsertBatch(buildCrudTransport(this.httpConfig), c, d);
|
|
2675
3035
|
}
|
|
3036
|
+
async upsertBatchRaw(c, d) {
|
|
3037
|
+
this.ensureInitialized();
|
|
3038
|
+
return upsertBatchRaw(buildRawBulkTransport(this.httpConfig), c, d, d[0]?.vector.length ?? 0);
|
|
3039
|
+
}
|
|
2676
3040
|
async delete(c, id) {
|
|
2677
3041
|
this.ensureInitialized();
|
|
2678
3042
|
return deletePoint(buildCrudTransport(this.httpConfig), c, id);
|
|
@@ -2738,6 +3102,22 @@ var RestBackend = class {
|
|
|
2738
3102
|
this.ensureInitialized();
|
|
2739
3103
|
return graphSearch(buildBaseTransport(this.httpConfig), c, r);
|
|
2740
3104
|
}
|
|
3105
|
+
async relate(c, req) {
|
|
3106
|
+
this.ensureInitialized();
|
|
3107
|
+
return relate(buildCrudTransport(this.httpConfig), c, req);
|
|
3108
|
+
}
|
|
3109
|
+
async unrelate(c, edgeId) {
|
|
3110
|
+
this.ensureInitialized();
|
|
3111
|
+
return unrelate(buildCrudTransport(this.httpConfig), c, edgeId);
|
|
3112
|
+
}
|
|
3113
|
+
async getRelations(c, pointId) {
|
|
3114
|
+
this.ensureInitialized();
|
|
3115
|
+
return getRelations(buildCrudTransport(this.httpConfig), c, pointId);
|
|
3116
|
+
}
|
|
3117
|
+
async setTtlDurable(c, pointId, ttlSeconds) {
|
|
3118
|
+
this.ensureInitialized();
|
|
3119
|
+
return setTtlDurable(buildCrudTransport(this.httpConfig), c, pointId, ttlSeconds);
|
|
3120
|
+
}
|
|
2741
3121
|
// Search
|
|
2742
3122
|
async search(c, q, o) {
|
|
2743
3123
|
this.ensureInitialized();
|
|
@@ -2759,6 +3139,10 @@ var RestBackend = class {
|
|
|
2759
3139
|
this.ensureInitialized();
|
|
2760
3140
|
return multiQuerySearch(buildSearchTransport(this.httpConfig), c, v, o);
|
|
2761
3141
|
}
|
|
3142
|
+
async multiQuerySearchIds(c, v, o) {
|
|
3143
|
+
this.ensureInitialized();
|
|
3144
|
+
return multiQuerySearchIds(buildSearchTransport(this.httpConfig), c, v, o);
|
|
3145
|
+
}
|
|
2762
3146
|
async searchIds(c, q, o) {
|
|
2763
3147
|
this.ensureInitialized();
|
|
2764
3148
|
return searchIds(buildSearchTransport(this.httpConfig), c, q, o);
|
|
@@ -2845,6 +3229,10 @@ var RestBackend = class {
|
|
|
2845
3229
|
this.ensureInitialized();
|
|
2846
3230
|
return trainPq(buildStreamingTransport(this.httpConfig), c, o);
|
|
2847
3231
|
}
|
|
3232
|
+
async enableStreaming(c, cfg) {
|
|
3233
|
+
this.ensureInitialized();
|
|
3234
|
+
return enableStreaming(buildStreamingTransport(this.httpConfig), c, cfg);
|
|
3235
|
+
}
|
|
2848
3236
|
async streamInsert(c, d) {
|
|
2849
3237
|
this.ensureInitialized();
|
|
2850
3238
|
return streamInsert(buildStreamingTransport(this.httpConfig), c, d);
|
|
@@ -2870,6 +3258,14 @@ var RestBackend = class {
|
|
|
2870
3258
|
this.ensureInitialized();
|
|
2871
3259
|
return recallEpisodicEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, e, k);
|
|
2872
3260
|
}
|
|
3261
|
+
async recallRecentEvents(c, since) {
|
|
3262
|
+
this.ensureInitialized();
|
|
3263
|
+
return recallRecentEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, since);
|
|
3264
|
+
}
|
|
3265
|
+
async recallOlderThanEvents(c, before) {
|
|
3266
|
+
this.ensureInitialized();
|
|
3267
|
+
return recallOlderThanEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, before);
|
|
3268
|
+
}
|
|
2873
3269
|
async storeProceduralPattern(c, p) {
|
|
2874
3270
|
this.ensureInitialized();
|
|
2875
3271
|
return storeProceduralPattern(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, p);
|
|
@@ -2907,15 +3303,29 @@ var AgentMemoryClient = class {
|
|
|
2907
3303
|
async searchFacts(collection, embedding, k = 5) {
|
|
2908
3304
|
return this.backend.searchSemanticMemory(collection, embedding, k);
|
|
2909
3305
|
}
|
|
2910
|
-
/** Record an episodic event. Returns the
|
|
3306
|
+
/** Record an episodic event. Returns the point ID (string, u64-safe). */
|
|
2911
3307
|
async recordEvent(collection, event) {
|
|
2912
3308
|
return this.backend.recordEpisodicEvent(collection, event);
|
|
2913
3309
|
}
|
|
2914
|
-
/** Recall episodic events */
|
|
3310
|
+
/** Recall episodic events by vector similarity. */
|
|
2915
3311
|
async recallEvents(collection, embedding, k = 5) {
|
|
2916
3312
|
return this.backend.recallEpisodicEvents(collection, embedding, k);
|
|
2917
3313
|
}
|
|
2918
|
-
/**
|
|
3314
|
+
/**
|
|
3315
|
+
* Recall episodic events most-recent-first, optionally bounded below by
|
|
3316
|
+
* `since` (inclusive unix-seconds). Mirrors core `episodic.recent(since)`.
|
|
3317
|
+
*/
|
|
3318
|
+
async recallRecent(collection, since) {
|
|
3319
|
+
return this.backend.recallRecentEvents(collection, since);
|
|
3320
|
+
}
|
|
3321
|
+
/**
|
|
3322
|
+
* Recall episodic events strictly older than `before` (unix-seconds),
|
|
3323
|
+
* most-recent-first. Mirrors core `episodic.older_than(before)`.
|
|
3324
|
+
*/
|
|
3325
|
+
async recallOlderThan(collection, before) {
|
|
3326
|
+
return this.backend.recallOlderThanEvents(collection, before);
|
|
3327
|
+
}
|
|
3328
|
+
/** Store a procedural pattern. Returns the point ID (string, u64-safe). */
|
|
2919
3329
|
async learnProcedure(collection, pattern) {
|
|
2920
3330
|
return this.backend.storeProceduralPattern(collection, pattern);
|
|
2921
3331
|
}
|
|
@@ -2923,7 +3333,12 @@ var AgentMemoryClient = class {
|
|
|
2923
3333
|
async recallProcedures(collection, embedding, k = 5) {
|
|
2924
3334
|
return this.backend.matchProceduralPatterns(collection, embedding, k);
|
|
2925
3335
|
}
|
|
2926
|
-
/**
|
|
3336
|
+
/**
|
|
3337
|
+
* Delete a memory entry (fact, event, or procedure) by its point ID.
|
|
3338
|
+
*
|
|
3339
|
+
* Accepts the `string` ids returned by `recordEvent` / `learnProcedure`
|
|
3340
|
+
* (u64-safe decimal strings) as well as numeric ids.
|
|
3341
|
+
*/
|
|
2927
3342
|
async deleteMemory(collection, id) {
|
|
2928
3343
|
return this.backend.delete(collection, id);
|
|
2929
3344
|
}
|
|
@@ -2957,11 +3372,10 @@ function validateDocument(doc, config) {
|
|
|
2957
3372
|
validateRestPointId(doc.id, config);
|
|
2958
3373
|
}
|
|
2959
3374
|
function validateRestPointId(id, config) {
|
|
2960
|
-
if (config.backend
|
|
2961
|
-
|
|
2962
|
-
`REST backend requires numeric u64-compatible document IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER})`
|
|
2963
|
-
);
|
|
3375
|
+
if (config.backend !== "rest") {
|
|
3376
|
+
return;
|
|
2964
3377
|
}
|
|
3378
|
+
parseRestPointId(id);
|
|
2965
3379
|
}
|
|
2966
3380
|
|
|
2967
3381
|
// src/client/search-methods.ts
|
|
@@ -3001,9 +3415,21 @@ function multiQuerySearch2(backend, collection, vectors, options) {
|
|
|
3001
3415
|
}
|
|
3002
3416
|
return backend.multiQuerySearch(collection, vectors, options);
|
|
3003
3417
|
}
|
|
3418
|
+
function multiQuerySearchIds2(backend, collection, vectors, options) {
|
|
3419
|
+
if (!Array.isArray(vectors) || vectors.length === 0) {
|
|
3420
|
+
throw new ValidationError("Vectors must be a non-empty array");
|
|
3421
|
+
}
|
|
3422
|
+
for (const v of vectors) {
|
|
3423
|
+
requireVector(v, "Each vector");
|
|
3424
|
+
}
|
|
3425
|
+
return backend.multiQuerySearchIds(collection, vectors, options);
|
|
3426
|
+
}
|
|
3004
3427
|
function trainPq2(backend, collection, options) {
|
|
3005
3428
|
return backend.trainPq(collection, options);
|
|
3006
3429
|
}
|
|
3430
|
+
function enableStreaming2(backend, collection, config) {
|
|
3431
|
+
return backend.enableStreaming(collection, config);
|
|
3432
|
+
}
|
|
3007
3433
|
function streamInsert2(backend, config, collection, docs) {
|
|
3008
3434
|
validateDocsBatch(docs, (doc) => {
|
|
3009
3435
|
validateDocument(doc, config);
|
|
@@ -3142,6 +3568,40 @@ function graphSearch2(backend, collection, request2) {
|
|
|
3142
3568
|
requireNonEmptyString(collection, "Collection");
|
|
3143
3569
|
return backend.graphSearch(collection, request2);
|
|
3144
3570
|
}
|
|
3571
|
+
function relate2(backend, collection, req) {
|
|
3572
|
+
requireNonEmptyString(collection, "Collection");
|
|
3573
|
+
if (!req.relType || typeof req.relType !== "string") {
|
|
3574
|
+
throw new ValidationError("Relation type is required and must be a string");
|
|
3575
|
+
}
|
|
3576
|
+
if (!isGraphNodeId(req.source) || !isGraphNodeId(req.target)) {
|
|
3577
|
+
throw new ValidationError("Source and target must be numbers or strings");
|
|
3578
|
+
}
|
|
3579
|
+
return backend.relate(collection, req);
|
|
3580
|
+
}
|
|
3581
|
+
function unrelate2(backend, collection, edgeId) {
|
|
3582
|
+
requireNonEmptyString(collection, "Collection");
|
|
3583
|
+
if (!isGraphNodeId(edgeId)) {
|
|
3584
|
+
throw new ValidationError("Edge ID must be a number or string");
|
|
3585
|
+
}
|
|
3586
|
+
return backend.unrelate(collection, edgeId);
|
|
3587
|
+
}
|
|
3588
|
+
function getRelations2(backend, collection, pointId) {
|
|
3589
|
+
requireNonEmptyString(collection, "Collection");
|
|
3590
|
+
if (!isGraphNodeId(pointId)) {
|
|
3591
|
+
throw new ValidationError("Point ID must be a number or string");
|
|
3592
|
+
}
|
|
3593
|
+
return backend.getRelations(collection, pointId);
|
|
3594
|
+
}
|
|
3595
|
+
function setTtlDurable2(backend, collection, pointId, ttlSeconds) {
|
|
3596
|
+
requireNonEmptyString(collection, "Collection");
|
|
3597
|
+
if (!isGraphNodeId(pointId)) {
|
|
3598
|
+
throw new ValidationError("Point ID must be a number or string");
|
|
3599
|
+
}
|
|
3600
|
+
if (typeof ttlSeconds !== "number" || ttlSeconds < 0) {
|
|
3601
|
+
throw new ValidationError("ttlSeconds must be a non-negative number");
|
|
3602
|
+
}
|
|
3603
|
+
return backend.setTtlDurable(collection, pointId, ttlSeconds);
|
|
3604
|
+
}
|
|
3145
3605
|
|
|
3146
3606
|
// src/client.ts
|
|
3147
3607
|
var VelesDB = class {
|
|
@@ -3238,6 +3698,24 @@ var VelesDB = class {
|
|
|
3238
3698
|
});
|
|
3239
3699
|
await this.backend.upsertBatch(collection, docs);
|
|
3240
3700
|
}
|
|
3701
|
+
/**
|
|
3702
|
+
* Bulk upsert via the binary wire format (REST backend only).
|
|
3703
|
+
*
|
|
3704
|
+
* Encodes `(id, vector)` pairs into the deterministic VRB1 binary layout
|
|
3705
|
+
* and sends them as a single `application/octet-stream` request, avoiding
|
|
3706
|
+
* per-point JSON overhead. Payloads are not carried — use
|
|
3707
|
+
* {@link upsertBatch} when you need them. Throws a not-supported error on
|
|
3708
|
+
* the WASM backend.
|
|
3709
|
+
*
|
|
3710
|
+
* @returns the number of points the server reports as inserted.
|
|
3711
|
+
*/
|
|
3712
|
+
async upsertBatchRaw(collection, docs) {
|
|
3713
|
+
this.ensureInitialized();
|
|
3714
|
+
validateDocsBatch(docs, (doc) => {
|
|
3715
|
+
validateDocument(doc, this.config);
|
|
3716
|
+
});
|
|
3717
|
+
return this.backend.upsertBatchRaw(collection, docs);
|
|
3718
|
+
}
|
|
3241
3719
|
async delete(collection, id) {
|
|
3242
3720
|
this.ensureInitialized();
|
|
3243
3721
|
validateRestPointId(id, this.config);
|
|
@@ -3285,6 +3763,11 @@ var VelesDB = class {
|
|
|
3285
3763
|
this.ensureInitialized();
|
|
3286
3764
|
return multiQuerySearch2(this.backend, collection, vectors, options);
|
|
3287
3765
|
}
|
|
3766
|
+
/** Multi-query fusion search returning only IDs and scores (no payloads). */
|
|
3767
|
+
async multiQuerySearchIds(collection, vectors, options) {
|
|
3768
|
+
this.ensureInitialized();
|
|
3769
|
+
return multiQuerySearchIds2(this.backend, collection, vectors, options);
|
|
3770
|
+
}
|
|
3288
3771
|
/**
|
|
3289
3772
|
* Pure sparse search against a named sparse index.
|
|
3290
3773
|
*
|
|
@@ -3315,6 +3798,10 @@ var VelesDB = class {
|
|
|
3315
3798
|
this.ensureInitialized();
|
|
3316
3799
|
return trainPq2(this.backend, collection, options);
|
|
3317
3800
|
}
|
|
3801
|
+
async enableStreaming(collection, config) {
|
|
3802
|
+
this.ensureInitialized();
|
|
3803
|
+
return enableStreaming2(this.backend, collection, config);
|
|
3804
|
+
}
|
|
3318
3805
|
async streamInsert(collection, docs) {
|
|
3319
3806
|
this.ensureInitialized();
|
|
3320
3807
|
return streamInsert2(this.backend, this.config, collection, docs);
|
|
@@ -3439,6 +3926,22 @@ var VelesDB = class {
|
|
|
3439
3926
|
this.ensureInitialized();
|
|
3440
3927
|
return graphSearch2(this.backend, collection, request2);
|
|
3441
3928
|
}
|
|
3929
|
+
async relate(collection, req) {
|
|
3930
|
+
this.ensureInitialized();
|
|
3931
|
+
return relate2(this.backend, collection, req);
|
|
3932
|
+
}
|
|
3933
|
+
async unrelate(collection, edgeId) {
|
|
3934
|
+
this.ensureInitialized();
|
|
3935
|
+
return unrelate2(this.backend, collection, edgeId);
|
|
3936
|
+
}
|
|
3937
|
+
async getRelations(collection, pointId) {
|
|
3938
|
+
this.ensureInitialized();
|
|
3939
|
+
return getRelations2(this.backend, collection, pointId);
|
|
3940
|
+
}
|
|
3941
|
+
async setTtlDurable(collection, pointId, ttlSeconds) {
|
|
3942
|
+
this.ensureInitialized();
|
|
3943
|
+
return setTtlDurable2(this.backend, collection, pointId, ttlSeconds);
|
|
3944
|
+
}
|
|
3442
3945
|
// ========================================================================
|
|
3443
3946
|
// Capabilities & Backend Info
|
|
3444
3947
|
// ========================================================================
|