@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.mjs
CHANGED
|
@@ -43,6 +43,7 @@ var REST_CAPABILITIES = Object.freeze({
|
|
|
43
43
|
graphTraversal: true,
|
|
44
44
|
secondaryIndexes: true,
|
|
45
45
|
agentMemory: true,
|
|
46
|
+
enableStreaming: true,
|
|
46
47
|
streamInsert: true,
|
|
47
48
|
pqTraining: true,
|
|
48
49
|
velesqlQuery: true,
|
|
@@ -58,9 +59,10 @@ var WASM_CAPABILITIES = Object.freeze({
|
|
|
58
59
|
graphTraversal: false,
|
|
59
60
|
secondaryIndexes: false,
|
|
60
61
|
agentMemory: false,
|
|
62
|
+
enableStreaming: false,
|
|
61
63
|
streamInsert: false,
|
|
62
64
|
pqTraining: false,
|
|
63
|
-
velesqlQuery:
|
|
65
|
+
velesqlQuery: false,
|
|
64
66
|
collectionIntrospection: false
|
|
65
67
|
});
|
|
66
68
|
|
|
@@ -298,20 +300,47 @@ async function wasmMultiQuerySearch(ctx, collectionName, vectors, options) {
|
|
|
298
300
|
);
|
|
299
301
|
return raw.map((r) => mapWasmResult(ctx, collection, r));
|
|
300
302
|
}
|
|
301
|
-
|
|
303
|
+
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;
|
|
304
|
+
function parsePureNearQuery(queryString) {
|
|
305
|
+
const match = PURE_NEAR_QUERY.exec(queryString);
|
|
306
|
+
if (!match) {
|
|
307
|
+
throw new VelesDBError(
|
|
308
|
+
`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}`,
|
|
309
|
+
"NOT_SUPPORTED"
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
const parsed = { from: match[1], param: match[2] };
|
|
313
|
+
if (match[3] !== void 0) {
|
|
314
|
+
parsed.limit = Number(match[3]);
|
|
315
|
+
}
|
|
316
|
+
return parsed;
|
|
317
|
+
}
|
|
318
|
+
function resolveQueryK(limit, requestedK) {
|
|
319
|
+
if (limit !== void 0) {
|
|
320
|
+
return limit;
|
|
321
|
+
}
|
|
322
|
+
return typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
|
|
323
|
+
}
|
|
324
|
+
async function wasmQuery(ctx, collectionName, queryString, params, _options) {
|
|
302
325
|
const collection = ctx.getCollection(collectionName);
|
|
303
326
|
if (!collection) {
|
|
304
327
|
throw new NotFoundError(`Collection '${collectionName}'`);
|
|
305
328
|
}
|
|
306
|
-
const
|
|
329
|
+
const parsed = parsePureNearQuery(queryString);
|
|
330
|
+
if (parsed.from !== collectionName) {
|
|
331
|
+
throw new VelesDBError(
|
|
332
|
+
`Query targets collection '${parsed.from}' but was executed against '${collectionName}'.`,
|
|
333
|
+
"BAD_REQUEST"
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
const paramsVector = params?.[parsed.param];
|
|
307
337
|
if (!Array.isArray(paramsVector) && !(paramsVector instanceof Float32Array)) {
|
|
308
338
|
throw new VelesDBError(
|
|
309
|
-
|
|
339
|
+
`WASM query() expects params.${parsed.param} to contain the query embedding vector.`,
|
|
310
340
|
"BAD_REQUEST"
|
|
311
341
|
);
|
|
312
342
|
}
|
|
313
|
-
const
|
|
314
|
-
const k = typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
|
|
343
|
+
const k = resolveQueryK(parsed.limit, params?.k);
|
|
315
344
|
const raw = collection.store.query(
|
|
316
345
|
paramsVector instanceof Float32Array ? paramsVector : new Float32Array(paramsVector),
|
|
317
346
|
k
|
|
@@ -725,6 +754,9 @@ function validateCollectionName(name) {
|
|
|
725
754
|
);
|
|
726
755
|
}
|
|
727
756
|
}
|
|
757
|
+
async function safeJsonParse(response) {
|
|
758
|
+
return response.json().catch(() => ({}));
|
|
759
|
+
}
|
|
728
760
|
function toNumberArray(v) {
|
|
729
761
|
return v instanceof Float32Array ? Array.from(v) : v;
|
|
730
762
|
}
|
|
@@ -778,12 +810,18 @@ async function wasmScroll(_collection, _request) {
|
|
|
778
810
|
async function wasmTrainPq(_collection, _options) {
|
|
779
811
|
wasmNotSupported("PQ training");
|
|
780
812
|
}
|
|
813
|
+
async function wasmEnableStreaming(_collection, _config) {
|
|
814
|
+
wasmNotSupported("Streaming enable");
|
|
815
|
+
}
|
|
781
816
|
async function wasmStreamInsert(_collection, _docs) {
|
|
782
817
|
wasmNotSupported("Streaming insert");
|
|
783
818
|
}
|
|
784
819
|
async function wasmStreamUpsertPoints(_collection, _docs) {
|
|
785
820
|
wasmNotSupported("Streaming batch upsert");
|
|
786
821
|
}
|
|
822
|
+
async function wasmUpsertBatchRaw(_collection, _docs) {
|
|
823
|
+
wasmNotSupported("Binary bulk upsert (upsertBatchRaw)");
|
|
824
|
+
}
|
|
787
825
|
async function wasmCreateGraphCollection(_name, _config) {
|
|
788
826
|
wasmNotSupported("Graph collections");
|
|
789
827
|
}
|
|
@@ -799,6 +837,9 @@ async function wasmGetCollectionConfig(_collection) {
|
|
|
799
837
|
async function wasmSearchIds(_collection, _query, _options) {
|
|
800
838
|
wasmNotSupported("searchIds");
|
|
801
839
|
}
|
|
840
|
+
async function wasmMultiQuerySearchIds(_collection, _vectors, _options) {
|
|
841
|
+
wasmNotSupported("multiQuerySearchIds");
|
|
842
|
+
}
|
|
802
843
|
async function wasmStoreSemanticFact(_collection, _entry) {
|
|
803
844
|
wasmNotSupported("Agent memory");
|
|
804
845
|
}
|
|
@@ -811,6 +852,12 @@ async function wasmRecordEpisodicEvent(_collection, _event) {
|
|
|
811
852
|
async function wasmRecallEpisodicEvents(_collection, _embedding, _k) {
|
|
812
853
|
wasmNotSupported("Agent memory");
|
|
813
854
|
}
|
|
855
|
+
async function wasmRecallRecentEvents(_collection, _since) {
|
|
856
|
+
wasmNotSupported("Agent memory");
|
|
857
|
+
}
|
|
858
|
+
async function wasmRecallOlderThanEvents(_collection, _before) {
|
|
859
|
+
wasmNotSupported("Agent memory");
|
|
860
|
+
}
|
|
814
861
|
async function wasmStoreProceduralPattern(_collection, _pattern) {
|
|
815
862
|
wasmNotSupported("Agent memory");
|
|
816
863
|
}
|
|
@@ -858,6 +905,18 @@ function wasmUpsertNodePayload(_c, _id, _p) {
|
|
|
858
905
|
function wasmGraphSearch(_c, _r) {
|
|
859
906
|
return Promise.resolve(wasmNotSupported("Graph search"));
|
|
860
907
|
}
|
|
908
|
+
function wasmRelate(_c, _req) {
|
|
909
|
+
return Promise.resolve(wasmNotSupported("Relation edges"));
|
|
910
|
+
}
|
|
911
|
+
function wasmUnrelate(_c, _id) {
|
|
912
|
+
return Promise.resolve(wasmNotSupported("Relation edge removal"));
|
|
913
|
+
}
|
|
914
|
+
function wasmGetRelations(_c, _id) {
|
|
915
|
+
return Promise.resolve(wasmNotSupported("Relation edges"));
|
|
916
|
+
}
|
|
917
|
+
function wasmSetTtlDurable(_c, _id, _ttl) {
|
|
918
|
+
return Promise.resolve(wasmNotSupported("Durable TTL"));
|
|
919
|
+
}
|
|
861
920
|
|
|
862
921
|
// src/backends/wasm.ts
|
|
863
922
|
var WasmBackend = class {
|
|
@@ -1037,6 +1096,9 @@ var WasmBackend = class {
|
|
|
1037
1096
|
}
|
|
1038
1097
|
}
|
|
1039
1098
|
}
|
|
1099
|
+
async upsertBatchRaw(c, d) {
|
|
1100
|
+
return wasmUpsertBatchRaw(c, d);
|
|
1101
|
+
}
|
|
1040
1102
|
async delete(collectionName, id) {
|
|
1041
1103
|
this.ensureInitialized();
|
|
1042
1104
|
const collection = this.collections.get(collectionName);
|
|
@@ -1168,6 +1230,10 @@ var WasmBackend = class {
|
|
|
1168
1230
|
this.ensureInitialized();
|
|
1169
1231
|
return wasmTrainPq(c, o);
|
|
1170
1232
|
}
|
|
1233
|
+
async enableStreaming(c, cfg) {
|
|
1234
|
+
this.ensureInitialized();
|
|
1235
|
+
return wasmEnableStreaming(c, cfg);
|
|
1236
|
+
}
|
|
1171
1237
|
async streamInsert(c, d) {
|
|
1172
1238
|
this.ensureInitialized();
|
|
1173
1239
|
return wasmStreamInsert(c, d);
|
|
@@ -1196,6 +1262,10 @@ var WasmBackend = class {
|
|
|
1196
1262
|
this.ensureInitialized();
|
|
1197
1263
|
return wasmSearchIds(c, q, o);
|
|
1198
1264
|
}
|
|
1265
|
+
async multiQuerySearchIds(c, v, o) {
|
|
1266
|
+
this.ensureInitialized();
|
|
1267
|
+
return wasmMultiQuerySearchIds(c, v, o);
|
|
1268
|
+
}
|
|
1199
1269
|
async storeSemanticFact(c, e) {
|
|
1200
1270
|
this.ensureInitialized();
|
|
1201
1271
|
return wasmStoreSemanticFact(c, e);
|
|
@@ -1212,6 +1282,14 @@ var WasmBackend = class {
|
|
|
1212
1282
|
this.ensureInitialized();
|
|
1213
1283
|
return wasmRecallEpisodicEvents(c, e, k);
|
|
1214
1284
|
}
|
|
1285
|
+
async recallRecentEvents(c, since) {
|
|
1286
|
+
this.ensureInitialized();
|
|
1287
|
+
return wasmRecallRecentEvents(c, since);
|
|
1288
|
+
}
|
|
1289
|
+
async recallOlderThanEvents(c, before) {
|
|
1290
|
+
this.ensureInitialized();
|
|
1291
|
+
return wasmRecallOlderThanEvents(c, before);
|
|
1292
|
+
}
|
|
1215
1293
|
async storeProceduralPattern(c, p) {
|
|
1216
1294
|
this.ensureInitialized();
|
|
1217
1295
|
return wasmStoreProceduralPattern(c, p);
|
|
@@ -1273,16 +1351,46 @@ var WasmBackend = class {
|
|
|
1273
1351
|
this.ensureInitialized();
|
|
1274
1352
|
return wasmSparseSearchNamed(c, q, idx, o);
|
|
1275
1353
|
}
|
|
1354
|
+
async relate(c, req) {
|
|
1355
|
+
this.ensureInitialized();
|
|
1356
|
+
return wasmRelate(c, req);
|
|
1357
|
+
}
|
|
1358
|
+
async unrelate(c, edgeId) {
|
|
1359
|
+
this.ensureInitialized();
|
|
1360
|
+
return wasmUnrelate(c, edgeId);
|
|
1361
|
+
}
|
|
1362
|
+
async getRelations(c, pointId) {
|
|
1363
|
+
this.ensureInitialized();
|
|
1364
|
+
return wasmGetRelations(c, pointId);
|
|
1365
|
+
}
|
|
1366
|
+
async setTtlDurable(c, pointId, ttlSeconds) {
|
|
1367
|
+
this.ensureInitialized();
|
|
1368
|
+
return wasmSetTtlDurable(c, pointId, ttlSeconds);
|
|
1369
|
+
}
|
|
1276
1370
|
};
|
|
1277
1371
|
|
|
1278
1372
|
// src/backends/crud-backend.ts
|
|
1373
|
+
var RAW_BULK_HEADER_LEN = 16;
|
|
1374
|
+
var RAW_BULK_MAGIC = [86, 82, 66, 49];
|
|
1375
|
+
var RAW_BULK_ID_WIDTH = 8;
|
|
1376
|
+
var U64_MAX = 18446744073709551615n;
|
|
1377
|
+
function coerceDecimalStringId(id) {
|
|
1378
|
+
if (!/^\d+$/.test(id)) return NaN;
|
|
1379
|
+
const big = BigInt(id);
|
|
1380
|
+
if (big > U64_MAX) return NaN;
|
|
1381
|
+
return big > BigInt(Number.MAX_SAFE_INTEGER) ? id : Number(id);
|
|
1382
|
+
}
|
|
1279
1383
|
function parseRestPointId(id) {
|
|
1280
|
-
|
|
1384
|
+
const coerced = typeof id === "string" ? coerceDecimalStringId(id) : id;
|
|
1385
|
+
if (typeof coerced === "string") {
|
|
1386
|
+
return coerced;
|
|
1387
|
+
}
|
|
1388
|
+
if (!Number.isFinite(coerced) || coerced < 0 || !Number.isInteger(coerced) || coerced > Number.MAX_SAFE_INTEGER) {
|
|
1281
1389
|
throw new ValidationError(
|
|
1282
|
-
`REST backend requires numeric u64-compatible IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER}). Received: ${String(id)}`
|
|
1390
|
+
`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)}`
|
|
1283
1391
|
);
|
|
1284
1392
|
}
|
|
1285
|
-
return
|
|
1393
|
+
return coerced;
|
|
1286
1394
|
}
|
|
1287
1395
|
function sparseVectorToRestFormat(sv) {
|
|
1288
1396
|
const result = {};
|
|
@@ -1415,6 +1523,105 @@ async function flush(transport, collection) {
|
|
|
1415
1523
|
);
|
|
1416
1524
|
throwOnError(response, `Collection '${collection}'`);
|
|
1417
1525
|
}
|
|
1526
|
+
function encodeRawBulk(ids, vectors, dim) {
|
|
1527
|
+
const count = ids.length;
|
|
1528
|
+
if (vectors.length !== count) {
|
|
1529
|
+
throw new ValidationError(
|
|
1530
|
+
`encodeRawBulk: ids length (${count}) must match vectors length (${vectors.length})`
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
const buf = new Uint8Array(RAW_BULK_HEADER_LEN + count * 8 + count * dim * 4);
|
|
1534
|
+
const view = new DataView(buf.buffer);
|
|
1535
|
+
buf.set(RAW_BULK_MAGIC, 0);
|
|
1536
|
+
view.setUint32(4, count, true);
|
|
1537
|
+
view.setUint32(8, dim, true);
|
|
1538
|
+
buf[12] = RAW_BULK_ID_WIDTH;
|
|
1539
|
+
writeIds(view, ids);
|
|
1540
|
+
writeVectors(view, vectors, dim, count);
|
|
1541
|
+
return buf;
|
|
1542
|
+
}
|
|
1543
|
+
function writeIds(view, ids) {
|
|
1544
|
+
let off = RAW_BULK_HEADER_LEN;
|
|
1545
|
+
for (const id of ids) {
|
|
1546
|
+
view.setBigUint64(off, BigInt(id), true);
|
|
1547
|
+
off += 8;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
function writeVectors(view, vectors, dim, count) {
|
|
1551
|
+
let off = RAW_BULK_HEADER_LEN + count * 8;
|
|
1552
|
+
for (const vec of vectors) {
|
|
1553
|
+
if (vec.length !== dim) {
|
|
1554
|
+
throw new ValidationError(
|
|
1555
|
+
`encodeRawBulk: vector length (${vec.length}) must match dim (${dim})`
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1558
|
+
for (let i = 0; i < dim; i++) {
|
|
1559
|
+
view.setFloat32(off, vec[i] ?? 0, true);
|
|
1560
|
+
off += 4;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
async function upsertBatchRaw(transport, collection, docs, dim) {
|
|
1565
|
+
const ids = docs.map((d) => coerceNumericId(d.id));
|
|
1566
|
+
const vectors = docs.map((d) => d.vector);
|
|
1567
|
+
const body = encodeRawBulk(ids, vectors, dim);
|
|
1568
|
+
return sendRawBulk(transport, collection, body);
|
|
1569
|
+
}
|
|
1570
|
+
function coerceNumericId(id) {
|
|
1571
|
+
const parsed = parseRestPointId(id);
|
|
1572
|
+
if (typeof parsed === "string") {
|
|
1573
|
+
throw new ValidationError(
|
|
1574
|
+
`upsertBatchRaw requires ids in the JS safe integer range; received: ${parsed}`
|
|
1575
|
+
);
|
|
1576
|
+
}
|
|
1577
|
+
return parsed;
|
|
1578
|
+
}
|
|
1579
|
+
async function sendRawBulk(transport, collection, body) {
|
|
1580
|
+
const url = `${transport.baseUrl}${collectionPath(collection)}/points/raw`;
|
|
1581
|
+
const headers = {
|
|
1582
|
+
"Content-Type": "application/octet-stream"
|
|
1583
|
+
};
|
|
1584
|
+
if (transport.apiKey) {
|
|
1585
|
+
headers["Authorization"] = `Bearer ${transport.apiKey}`;
|
|
1586
|
+
}
|
|
1587
|
+
const controller = new AbortController();
|
|
1588
|
+
const timeoutId = setTimeout(() => controller.abort(), transport.timeout);
|
|
1589
|
+
try {
|
|
1590
|
+
const response = await fetch(url, {
|
|
1591
|
+
method: "POST",
|
|
1592
|
+
headers,
|
|
1593
|
+
body,
|
|
1594
|
+
signal: controller.signal
|
|
1595
|
+
});
|
|
1596
|
+
clearTimeout(timeoutId);
|
|
1597
|
+
return await parseRawBulkResponse(response);
|
|
1598
|
+
} catch (error) {
|
|
1599
|
+
clearTimeout(timeoutId);
|
|
1600
|
+
throw wrapRawBulkError(error);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
async function parseRawBulkResponse(response) {
|
|
1604
|
+
const data = await safeJsonParse(response);
|
|
1605
|
+
if (!response.ok) {
|
|
1606
|
+
const code = typeof data.code === "string" ? data.code : `HTTP_${response.status}`;
|
|
1607
|
+
const message = typeof data.error === "string" ? data.error : `HTTP ${response.status}`;
|
|
1608
|
+
throw new VelesDBError(message, code);
|
|
1609
|
+
}
|
|
1610
|
+
return typeof data.count === "number" ? data.count : 0;
|
|
1611
|
+
}
|
|
1612
|
+
function wrapRawBulkError(error) {
|
|
1613
|
+
if (error instanceof VelesDBError) {
|
|
1614
|
+
return error;
|
|
1615
|
+
}
|
|
1616
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
1617
|
+
return new ConnectionError("Request timeout");
|
|
1618
|
+
}
|
|
1619
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1620
|
+
return new ConnectionError(
|
|
1621
|
+
`Raw bulk upsert failed: ${message}`,
|
|
1622
|
+
error instanceof Error ? error : void 0
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1418
1625
|
|
|
1419
1626
|
// src/backends/rest-http.ts
|
|
1420
1627
|
var STATUS_ERROR_CODES = {
|
|
@@ -1485,7 +1692,7 @@ async function request(config, method, path, body) {
|
|
|
1485
1692
|
signal: controller.signal
|
|
1486
1693
|
});
|
|
1487
1694
|
clearTimeout(timeoutId);
|
|
1488
|
-
const data = await response
|
|
1695
|
+
const data = await safeJsonParse(response);
|
|
1489
1696
|
if (!response.ok) {
|
|
1490
1697
|
const ep = extractErrorPayload(data);
|
|
1491
1698
|
return { error: {
|
|
@@ -1509,6 +1716,13 @@ function buildCrudTransport(config) {
|
|
|
1509
1716
|
requestJson: (m, p, b) => request(config, m, p, b)
|
|
1510
1717
|
};
|
|
1511
1718
|
}
|
|
1719
|
+
function buildRawBulkTransport(config) {
|
|
1720
|
+
return {
|
|
1721
|
+
baseUrl: config.baseUrl,
|
|
1722
|
+
apiKey: config.apiKey,
|
|
1723
|
+
timeout: config.timeout
|
|
1724
|
+
};
|
|
1725
|
+
}
|
|
1512
1726
|
function buildSearchTransport(config) {
|
|
1513
1727
|
return {
|
|
1514
1728
|
requestJson: (m, p, b) => request(config, m, p, b),
|
|
@@ -1737,6 +1951,31 @@ async function graphSearch(transport, collection, request2) {
|
|
|
1737
1951
|
return { results: items };
|
|
1738
1952
|
}
|
|
1739
1953
|
|
|
1954
|
+
// src/backends/scroll-backend.ts
|
|
1955
|
+
async function scroll(transport, collection, request2) {
|
|
1956
|
+
const body = {};
|
|
1957
|
+
if (request2?.cursor !== void 0) {
|
|
1958
|
+
body.cursor = request2.cursor;
|
|
1959
|
+
}
|
|
1960
|
+
if (request2?.batchSize !== void 0) {
|
|
1961
|
+
body.batch_size = request2.batchSize;
|
|
1962
|
+
}
|
|
1963
|
+
if (request2?.filter !== void 0) {
|
|
1964
|
+
body.filter = request2.filter;
|
|
1965
|
+
}
|
|
1966
|
+
const response = await transport.requestJson(
|
|
1967
|
+
"POST",
|
|
1968
|
+
`${collectionPath(collection)}/points/scroll`,
|
|
1969
|
+
body
|
|
1970
|
+
);
|
|
1971
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
1972
|
+
const data = response.data;
|
|
1973
|
+
return {
|
|
1974
|
+
points: data.points,
|
|
1975
|
+
nextCursor: data.next_cursor
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1740
1979
|
// src/backends/agent-memory-backend.ts
|
|
1741
1980
|
var _idCounter = 0;
|
|
1742
1981
|
var _lastTimestamp = 0;
|
|
@@ -1754,20 +1993,28 @@ function generateUniqueId() {
|
|
|
1754
1993
|
}
|
|
1755
1994
|
return _lastTimestamp * 1e3 + _idCounter;
|
|
1756
1995
|
}
|
|
1996
|
+
function memoryIdToString(id) {
|
|
1997
|
+
return String(id);
|
|
1998
|
+
}
|
|
1999
|
+
function nowUnixSeconds() {
|
|
2000
|
+
return Math.floor(Date.now() / 1e3);
|
|
2001
|
+
}
|
|
1757
2002
|
async function storeSemanticFact(transport, collection, entry) {
|
|
1758
2003
|
const response = await transport.requestJson(
|
|
1759
2004
|
"POST",
|
|
1760
2005
|
`${collectionPath(collection)}/points`,
|
|
1761
2006
|
{
|
|
1762
2007
|
points: [{
|
|
1763
|
-
id: entry.id,
|
|
2008
|
+
id: parseRestPointId(entry.id),
|
|
1764
2009
|
vector: entry.embedding,
|
|
1765
2010
|
payload: {
|
|
1766
2011
|
// Caller metadata is spread first so the reserved keys below
|
|
1767
|
-
// (`_memory_type`, `
|
|
2012
|
+
// (`_memory_type`, `content`) always win and cannot be clobbered.
|
|
1768
2013
|
...entry.metadata,
|
|
1769
2014
|
_memory_type: "semantic",
|
|
1770
|
-
|
|
2015
|
+
// `content` matches the core semantic store and the server/Python
|
|
2016
|
+
// payload field (BREAKING: was `text` before this change).
|
|
2017
|
+
content: entry.text
|
|
1771
2018
|
}
|
|
1772
2019
|
}]
|
|
1773
2020
|
}
|
|
@@ -1778,7 +2025,8 @@ async function searchSemanticMemory(transport, collection, embedding, k = 5) {
|
|
|
1778
2025
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "semantic" });
|
|
1779
2026
|
}
|
|
1780
2027
|
async function recordEpisodicEvent(transport, collection, event) {
|
|
1781
|
-
const id = generateUniqueId();
|
|
2028
|
+
const id = event.id !== void 0 ? parseRestPointId(event.id) : generateUniqueId();
|
|
2029
|
+
const timestamp = event.timestamp ?? nowUnixSeconds();
|
|
1782
2030
|
const response = await transport.requestJson(
|
|
1783
2031
|
"POST",
|
|
1784
2032
|
`${collectionPath(collection)}/points`,
|
|
@@ -1794,19 +2042,21 @@ async function recordEpisodicEvent(transport, collection, event) {
|
|
|
1794
2042
|
...event.metadata,
|
|
1795
2043
|
_memory_type: "episodic",
|
|
1796
2044
|
event_type: event.eventType,
|
|
1797
|
-
|
|
2045
|
+
// NUMERIC unix-seconds, mirroring the core episodic store so
|
|
2046
|
+
// recallRecent/recallOlderThan can range-filter on it.
|
|
2047
|
+
timestamp
|
|
1798
2048
|
}
|
|
1799
2049
|
}]
|
|
1800
2050
|
}
|
|
1801
2051
|
);
|
|
1802
2052
|
throwOnError(response);
|
|
1803
|
-
return id;
|
|
2053
|
+
return memoryIdToString(id);
|
|
1804
2054
|
}
|
|
1805
2055
|
async function recallEpisodicEvents(transport, collection, embedding, k = 5) {
|
|
1806
2056
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "episodic" });
|
|
1807
2057
|
}
|
|
1808
2058
|
async function storeProceduralPattern(transport, collection, pattern) {
|
|
1809
|
-
const id = generateUniqueId();
|
|
2059
|
+
const id = pattern.id !== void 0 ? parseRestPointId(pattern.id) : generateUniqueId();
|
|
1810
2060
|
const response = await transport.requestJson(
|
|
1811
2061
|
"POST",
|
|
1812
2062
|
`${collectionPath(collection)}/points`,
|
|
@@ -1827,11 +2077,41 @@ async function storeProceduralPattern(transport, collection, pattern) {
|
|
|
1827
2077
|
}
|
|
1828
2078
|
);
|
|
1829
2079
|
throwOnError(response);
|
|
1830
|
-
return id;
|
|
2080
|
+
return memoryIdToString(id);
|
|
1831
2081
|
}
|
|
1832
2082
|
async function matchProceduralPatterns(transport, collection, embedding, k = 5) {
|
|
1833
2083
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "procedural" });
|
|
1834
2084
|
}
|
|
2085
|
+
function toEpisodicRecord(point) {
|
|
2086
|
+
const payload = point.payload ?? {};
|
|
2087
|
+
if (payload._memory_type !== "episodic") return void 0;
|
|
2088
|
+
if (typeof payload.timestamp !== "number") return void 0;
|
|
2089
|
+
return { id: String(point.id), timestamp: payload.timestamp, payload };
|
|
2090
|
+
}
|
|
2091
|
+
async function scrollEpisodicRecords(transport, collection) {
|
|
2092
|
+
const records = [];
|
|
2093
|
+
let cursor = null;
|
|
2094
|
+
do {
|
|
2095
|
+
const page = await scroll(transport, collection, {
|
|
2096
|
+
cursor: cursor ?? void 0,
|
|
2097
|
+
filter: { _memory_type: "episodic" }
|
|
2098
|
+
});
|
|
2099
|
+
for (const point of page.points) {
|
|
2100
|
+
const record = toEpisodicRecord(point);
|
|
2101
|
+
if (record !== void 0) records.push(record);
|
|
2102
|
+
}
|
|
2103
|
+
cursor = page.nextCursor;
|
|
2104
|
+
} while (cursor !== null && cursor !== void 0);
|
|
2105
|
+
return records;
|
|
2106
|
+
}
|
|
2107
|
+
async function recallRecentEvents(transport, collection, since) {
|
|
2108
|
+
const records = await scrollEpisodicRecords(transport, collection);
|
|
2109
|
+
return records.filter((r) => since === void 0 || r.timestamp >= since).sort((a, b) => b.timestamp - a.timestamp);
|
|
2110
|
+
}
|
|
2111
|
+
async function recallOlderThanEvents(transport, collection, before) {
|
|
2112
|
+
const records = await scrollEpisodicRecords(transport, collection);
|
|
2113
|
+
return records.filter((r) => r.timestamp < before).sort((a, b) => b.timestamp - a.timestamp);
|
|
2114
|
+
}
|
|
1835
2115
|
|
|
1836
2116
|
// src/search-quality.ts
|
|
1837
2117
|
function searchQualityToMode(quality) {
|
|
@@ -1930,6 +2210,22 @@ async function multiQuerySearch(transport, collection, vectors, options) {
|
|
|
1930
2210
|
throwOnError(response, `Collection '${collection}'`);
|
|
1931
2211
|
return response.data?.results ?? [];
|
|
1932
2212
|
}
|
|
2213
|
+
async function multiQuerySearchIds(transport, collection, vectors, options) {
|
|
2214
|
+
const formattedVectors = vectors.map(toNumberArray);
|
|
2215
|
+
const response = await transport.requestJson("POST", `${collectionPath(collection)}/search/multi/ids`, {
|
|
2216
|
+
vectors: formattedVectors,
|
|
2217
|
+
top_k: options?.k ?? 10,
|
|
2218
|
+
strategy: options?.fusion ?? "rrf",
|
|
2219
|
+
rrf_k: options?.fusionParams?.k ?? 60,
|
|
2220
|
+
avg_weight: options?.fusionParams?.avgWeight,
|
|
2221
|
+
max_weight: options?.fusionParams?.maxWeight,
|
|
2222
|
+
hit_weight: options?.fusionParams?.hitWeight,
|
|
2223
|
+
dense_weight: options?.fusionParams?.denseWeight,
|
|
2224
|
+
sparse_weight: options?.fusionParams?.sparseWeight
|
|
2225
|
+
});
|
|
2226
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2227
|
+
return response.data?.results ?? [];
|
|
2228
|
+
}
|
|
1933
2229
|
async function sparseSearchNamed(transport, collection, query3, indexName, options) {
|
|
1934
2230
|
const body = {
|
|
1935
2231
|
sparse_vectors: { [indexName]: transport.sparseToRest(query3) },
|
|
@@ -2064,6 +2360,64 @@ async function traverseParallel(transport, collection, request2) {
|
|
|
2064
2360
|
throwOnError(response, `Collection '${collection}'`);
|
|
2065
2361
|
return toTraverseResponse(response.data);
|
|
2066
2362
|
}
|
|
2363
|
+
async function relate(transport, collection, req) {
|
|
2364
|
+
const response = await transport.requestJson(
|
|
2365
|
+
"POST",
|
|
2366
|
+
`${collectionPath(collection)}/relations`,
|
|
2367
|
+
{
|
|
2368
|
+
source: req.source,
|
|
2369
|
+
target: req.target,
|
|
2370
|
+
rel_type: req.relType,
|
|
2371
|
+
properties: req.properties ?? {}
|
|
2372
|
+
}
|
|
2373
|
+
);
|
|
2374
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2375
|
+
return { edgeId: response.data.edge_id };
|
|
2376
|
+
}
|
|
2377
|
+
async function unrelate(transport, collection, edgeId) {
|
|
2378
|
+
const response = await transport.requestJson(
|
|
2379
|
+
"DELETE",
|
|
2380
|
+
`${collectionPath(collection)}/relations/${encodeURIComponent(String(edgeId))}`
|
|
2381
|
+
);
|
|
2382
|
+
if (response.error !== void 0) {
|
|
2383
|
+
const { code, message } = response.error;
|
|
2384
|
+
const err = parseVelesError(code, message);
|
|
2385
|
+
if (err instanceof EdgeNotFoundError) {
|
|
2386
|
+
return false;
|
|
2387
|
+
}
|
|
2388
|
+
if (code === "NOT_FOUND") {
|
|
2389
|
+
return false;
|
|
2390
|
+
}
|
|
2391
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2392
|
+
}
|
|
2393
|
+
return true;
|
|
2394
|
+
}
|
|
2395
|
+
async function getRelations(transport, collection, pointId) {
|
|
2396
|
+
const response = await transport.requestJson(
|
|
2397
|
+
"GET",
|
|
2398
|
+
`${collectionPath(collection)}/points/${encodeURIComponent(String(pointId))}/relations`
|
|
2399
|
+
);
|
|
2400
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2401
|
+
const raw = response.data;
|
|
2402
|
+
return {
|
|
2403
|
+
edges: raw.edges.map((e) => ({
|
|
2404
|
+
id: e.id,
|
|
2405
|
+
source: e.source,
|
|
2406
|
+
target: e.target,
|
|
2407
|
+
relType: e.rel_type,
|
|
2408
|
+
properties: e.properties
|
|
2409
|
+
})),
|
|
2410
|
+
count: raw.count
|
|
2411
|
+
};
|
|
2412
|
+
}
|
|
2413
|
+
async function setTtlDurable(transport, collection, pointId, ttlSeconds) {
|
|
2414
|
+
const response = await transport.requestJson(
|
|
2415
|
+
"PATCH",
|
|
2416
|
+
`${collectionPath(collection)}/points/${encodeURIComponent(String(pointId))}/ttl`,
|
|
2417
|
+
{ ttl_seconds: ttlSeconds }
|
|
2418
|
+
);
|
|
2419
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2420
|
+
}
|
|
2067
2421
|
|
|
2068
2422
|
// src/backends/query-backend.ts
|
|
2069
2423
|
function isLikelyAggregationQuery(queryString) {
|
|
@@ -2089,7 +2443,7 @@ async function query(transport, collection, queryString, params, options) {
|
|
|
2089
2443
|
);
|
|
2090
2444
|
throwOnError(response, `Collection '${collection}'`);
|
|
2091
2445
|
const rawData = response.data;
|
|
2092
|
-
if (rawData && Object.prototype.hasOwnProperty.call(rawData, "result")) {
|
|
2446
|
+
if (rawData != null && Object.prototype.hasOwnProperty.call(rawData, "result")) {
|
|
2093
2447
|
return {
|
|
2094
2448
|
result: rawData.result,
|
|
2095
2449
|
stats: {
|
|
@@ -2196,31 +2550,6 @@ async function collectionSanity(transport, collection) {
|
|
|
2196
2550
|
};
|
|
2197
2551
|
}
|
|
2198
2552
|
|
|
2199
|
-
// src/backends/scroll-backend.ts
|
|
2200
|
-
async function scroll(transport, collection, request2) {
|
|
2201
|
-
const body = {};
|
|
2202
|
-
if (request2?.cursor !== void 0) {
|
|
2203
|
-
body.cursor = request2.cursor;
|
|
2204
|
-
}
|
|
2205
|
-
if (request2?.batchSize !== void 0) {
|
|
2206
|
-
body.batch_size = request2.batchSize;
|
|
2207
|
-
}
|
|
2208
|
-
if (request2?.filter !== void 0) {
|
|
2209
|
-
body.filter = request2.filter;
|
|
2210
|
-
}
|
|
2211
|
-
const response = await transport.requestJson(
|
|
2212
|
-
"POST",
|
|
2213
|
-
`${collectionPath(collection)}/points/scroll`,
|
|
2214
|
-
body
|
|
2215
|
-
);
|
|
2216
|
-
throwOnError(response, `Collection '${collection}'`);
|
|
2217
|
-
const data = response.data;
|
|
2218
|
-
return {
|
|
2219
|
-
points: data.points,
|
|
2220
|
-
nextCursor: data.next_cursor
|
|
2221
|
-
};
|
|
2222
|
-
}
|
|
2223
|
-
|
|
2224
2553
|
// src/backends/admin-backend.ts
|
|
2225
2554
|
function mapStatsResponse(data) {
|
|
2226
2555
|
let columnStats;
|
|
@@ -2384,7 +2713,7 @@ async function streamInsert(transport, collection, docs) {
|
|
|
2384
2713
|
throw new BackpressureError();
|
|
2385
2714
|
}
|
|
2386
2715
|
if (!response.ok && response.status !== 202) {
|
|
2387
|
-
const data = await response
|
|
2716
|
+
const data = await safeJsonParse(response);
|
|
2388
2717
|
const errorPayload = transport.extractErrorPayload(data);
|
|
2389
2718
|
throw new VelesDBError(
|
|
2390
2719
|
errorPayload.message ?? `HTTP ${response.status}`,
|
|
@@ -2406,9 +2735,35 @@ async function streamInsert(transport, collection, docs) {
|
|
|
2406
2735
|
}
|
|
2407
2736
|
}
|
|
2408
2737
|
}
|
|
2738
|
+
async function enableStreaming(transport, collection, config) {
|
|
2739
|
+
const body = {};
|
|
2740
|
+
if (config?.bufferSize !== void 0) {
|
|
2741
|
+
body.buffer_size = config.bufferSize;
|
|
2742
|
+
}
|
|
2743
|
+
if (config?.batchSize !== void 0) {
|
|
2744
|
+
body.batch_size = config.batchSize;
|
|
2745
|
+
}
|
|
2746
|
+
if (config?.flushIntervalMs !== void 0) {
|
|
2747
|
+
body.flush_interval_ms = config.flushIntervalMs;
|
|
2748
|
+
}
|
|
2749
|
+
const response = await transport.requestJson(
|
|
2750
|
+
"POST",
|
|
2751
|
+
`${collectionPath(collection)}/stream/enable`,
|
|
2752
|
+
body
|
|
2753
|
+
);
|
|
2754
|
+
throwOnError(response);
|
|
2755
|
+
}
|
|
2756
|
+
function requireSafeRangeId(restId) {
|
|
2757
|
+
if (typeof restId === "string") {
|
|
2758
|
+
throw new ValidationError(
|
|
2759
|
+
`streamUpsertPoints requires ids in the JS safe integer range (0..${Number.MAX_SAFE_INTEGER}); use upsert/upsertBatch for string ids above it. Received: ${restId}`
|
|
2760
|
+
);
|
|
2761
|
+
}
|
|
2762
|
+
return restId;
|
|
2763
|
+
}
|
|
2409
2764
|
async function streamUpsertPoints(transport, collection, docs) {
|
|
2410
2765
|
const ndjsonLines = docs.map((doc) => {
|
|
2411
|
-
const restId = transport.parseRestPointId(doc.id);
|
|
2766
|
+
const restId = requireSafeRangeId(transport.parseRestPointId(doc.id));
|
|
2412
2767
|
const vector = toNumberArray(doc.vector);
|
|
2413
2768
|
const point = {
|
|
2414
2769
|
id: restId,
|
|
@@ -2442,14 +2797,14 @@ async function streamUpsertPoints(transport, collection, docs) {
|
|
|
2442
2797
|
throw new BackpressureError();
|
|
2443
2798
|
}
|
|
2444
2799
|
if (!response.ok) {
|
|
2445
|
-
const data2 = await response
|
|
2800
|
+
const data2 = await safeJsonParse(response);
|
|
2446
2801
|
const errorPayload = transport.extractErrorPayload(data2);
|
|
2447
2802
|
throw new VelesDBError(
|
|
2448
2803
|
errorPayload.message ?? `HTTP ${response.status}`,
|
|
2449
2804
|
errorPayload.code ?? transport.mapStatusToErrorCode(response.status)
|
|
2450
2805
|
);
|
|
2451
2806
|
}
|
|
2452
|
-
const data = await response
|
|
2807
|
+
const data = await safeJsonParse(response);
|
|
2453
2808
|
return {
|
|
2454
2809
|
message: typeof data.message === "string" ? data.message : "Stream processed",
|
|
2455
2810
|
inserted: typeof data.inserted === "number" ? data.inserted : 0,
|
|
@@ -2534,6 +2889,10 @@ var RestBackend = class {
|
|
|
2534
2889
|
this.ensureInitialized();
|
|
2535
2890
|
return upsertBatch(buildCrudTransport(this.httpConfig), c, d);
|
|
2536
2891
|
}
|
|
2892
|
+
async upsertBatchRaw(c, d) {
|
|
2893
|
+
this.ensureInitialized();
|
|
2894
|
+
return upsertBatchRaw(buildRawBulkTransport(this.httpConfig), c, d, d[0]?.vector.length ?? 0);
|
|
2895
|
+
}
|
|
2537
2896
|
async delete(c, id) {
|
|
2538
2897
|
this.ensureInitialized();
|
|
2539
2898
|
return deletePoint(buildCrudTransport(this.httpConfig), c, id);
|
|
@@ -2599,6 +2958,22 @@ var RestBackend = class {
|
|
|
2599
2958
|
this.ensureInitialized();
|
|
2600
2959
|
return graphSearch(buildBaseTransport(this.httpConfig), c, r);
|
|
2601
2960
|
}
|
|
2961
|
+
async relate(c, req) {
|
|
2962
|
+
this.ensureInitialized();
|
|
2963
|
+
return relate(buildCrudTransport(this.httpConfig), c, req);
|
|
2964
|
+
}
|
|
2965
|
+
async unrelate(c, edgeId) {
|
|
2966
|
+
this.ensureInitialized();
|
|
2967
|
+
return unrelate(buildCrudTransport(this.httpConfig), c, edgeId);
|
|
2968
|
+
}
|
|
2969
|
+
async getRelations(c, pointId) {
|
|
2970
|
+
this.ensureInitialized();
|
|
2971
|
+
return getRelations(buildCrudTransport(this.httpConfig), c, pointId);
|
|
2972
|
+
}
|
|
2973
|
+
async setTtlDurable(c, pointId, ttlSeconds) {
|
|
2974
|
+
this.ensureInitialized();
|
|
2975
|
+
return setTtlDurable(buildCrudTransport(this.httpConfig), c, pointId, ttlSeconds);
|
|
2976
|
+
}
|
|
2602
2977
|
// Search
|
|
2603
2978
|
async search(c, q, o) {
|
|
2604
2979
|
this.ensureInitialized();
|
|
@@ -2620,6 +2995,10 @@ var RestBackend = class {
|
|
|
2620
2995
|
this.ensureInitialized();
|
|
2621
2996
|
return multiQuerySearch(buildSearchTransport(this.httpConfig), c, v, o);
|
|
2622
2997
|
}
|
|
2998
|
+
async multiQuerySearchIds(c, v, o) {
|
|
2999
|
+
this.ensureInitialized();
|
|
3000
|
+
return multiQuerySearchIds(buildSearchTransport(this.httpConfig), c, v, o);
|
|
3001
|
+
}
|
|
2623
3002
|
async searchIds(c, q, o) {
|
|
2624
3003
|
this.ensureInitialized();
|
|
2625
3004
|
return searchIds(buildSearchTransport(this.httpConfig), c, q, o);
|
|
@@ -2706,6 +3085,10 @@ var RestBackend = class {
|
|
|
2706
3085
|
this.ensureInitialized();
|
|
2707
3086
|
return trainPq(buildStreamingTransport(this.httpConfig), c, o);
|
|
2708
3087
|
}
|
|
3088
|
+
async enableStreaming(c, cfg) {
|
|
3089
|
+
this.ensureInitialized();
|
|
3090
|
+
return enableStreaming(buildStreamingTransport(this.httpConfig), c, cfg);
|
|
3091
|
+
}
|
|
2709
3092
|
async streamInsert(c, d) {
|
|
2710
3093
|
this.ensureInitialized();
|
|
2711
3094
|
return streamInsert(buildStreamingTransport(this.httpConfig), c, d);
|
|
@@ -2731,6 +3114,14 @@ var RestBackend = class {
|
|
|
2731
3114
|
this.ensureInitialized();
|
|
2732
3115
|
return recallEpisodicEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, e, k);
|
|
2733
3116
|
}
|
|
3117
|
+
async recallRecentEvents(c, since) {
|
|
3118
|
+
this.ensureInitialized();
|
|
3119
|
+
return recallRecentEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, since);
|
|
3120
|
+
}
|
|
3121
|
+
async recallOlderThanEvents(c, before) {
|
|
3122
|
+
this.ensureInitialized();
|
|
3123
|
+
return recallOlderThanEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, before);
|
|
3124
|
+
}
|
|
2734
3125
|
async storeProceduralPattern(c, p) {
|
|
2735
3126
|
this.ensureInitialized();
|
|
2736
3127
|
return storeProceduralPattern(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, p);
|
|
@@ -2768,15 +3159,29 @@ var AgentMemoryClient = class {
|
|
|
2768
3159
|
async searchFacts(collection, embedding, k = 5) {
|
|
2769
3160
|
return this.backend.searchSemanticMemory(collection, embedding, k);
|
|
2770
3161
|
}
|
|
2771
|
-
/** Record an episodic event. Returns the
|
|
3162
|
+
/** Record an episodic event. Returns the point ID (string, u64-safe). */
|
|
2772
3163
|
async recordEvent(collection, event) {
|
|
2773
3164
|
return this.backend.recordEpisodicEvent(collection, event);
|
|
2774
3165
|
}
|
|
2775
|
-
/** Recall episodic events */
|
|
3166
|
+
/** Recall episodic events by vector similarity. */
|
|
2776
3167
|
async recallEvents(collection, embedding, k = 5) {
|
|
2777
3168
|
return this.backend.recallEpisodicEvents(collection, embedding, k);
|
|
2778
3169
|
}
|
|
2779
|
-
/**
|
|
3170
|
+
/**
|
|
3171
|
+
* Recall episodic events most-recent-first, optionally bounded below by
|
|
3172
|
+
* `since` (inclusive unix-seconds). Mirrors core `episodic.recent(since)`.
|
|
3173
|
+
*/
|
|
3174
|
+
async recallRecent(collection, since) {
|
|
3175
|
+
return this.backend.recallRecentEvents(collection, since);
|
|
3176
|
+
}
|
|
3177
|
+
/**
|
|
3178
|
+
* Recall episodic events strictly older than `before` (unix-seconds),
|
|
3179
|
+
* most-recent-first. Mirrors core `episodic.older_than(before)`.
|
|
3180
|
+
*/
|
|
3181
|
+
async recallOlderThan(collection, before) {
|
|
3182
|
+
return this.backend.recallOlderThanEvents(collection, before);
|
|
3183
|
+
}
|
|
3184
|
+
/** Store a procedural pattern. Returns the point ID (string, u64-safe). */
|
|
2780
3185
|
async learnProcedure(collection, pattern) {
|
|
2781
3186
|
return this.backend.storeProceduralPattern(collection, pattern);
|
|
2782
3187
|
}
|
|
@@ -2784,7 +3189,12 @@ var AgentMemoryClient = class {
|
|
|
2784
3189
|
async recallProcedures(collection, embedding, k = 5) {
|
|
2785
3190
|
return this.backend.matchProceduralPatterns(collection, embedding, k);
|
|
2786
3191
|
}
|
|
2787
|
-
/**
|
|
3192
|
+
/**
|
|
3193
|
+
* Delete a memory entry (fact, event, or procedure) by its point ID.
|
|
3194
|
+
*
|
|
3195
|
+
* Accepts the `string` ids returned by `recordEvent` / `learnProcedure`
|
|
3196
|
+
* (u64-safe decimal strings) as well as numeric ids.
|
|
3197
|
+
*/
|
|
2788
3198
|
async deleteMemory(collection, id) {
|
|
2789
3199
|
return this.backend.delete(collection, id);
|
|
2790
3200
|
}
|
|
@@ -2818,11 +3228,10 @@ function validateDocument(doc, config) {
|
|
|
2818
3228
|
validateRestPointId(doc.id, config);
|
|
2819
3229
|
}
|
|
2820
3230
|
function validateRestPointId(id, config) {
|
|
2821
|
-
if (config.backend
|
|
2822
|
-
|
|
2823
|
-
`REST backend requires numeric u64-compatible document IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER})`
|
|
2824
|
-
);
|
|
3231
|
+
if (config.backend !== "rest") {
|
|
3232
|
+
return;
|
|
2825
3233
|
}
|
|
3234
|
+
parseRestPointId(id);
|
|
2826
3235
|
}
|
|
2827
3236
|
|
|
2828
3237
|
// src/client/search-methods.ts
|
|
@@ -2862,9 +3271,21 @@ function multiQuerySearch2(backend, collection, vectors, options) {
|
|
|
2862
3271
|
}
|
|
2863
3272
|
return backend.multiQuerySearch(collection, vectors, options);
|
|
2864
3273
|
}
|
|
3274
|
+
function multiQuerySearchIds2(backend, collection, vectors, options) {
|
|
3275
|
+
if (!Array.isArray(vectors) || vectors.length === 0) {
|
|
3276
|
+
throw new ValidationError("Vectors must be a non-empty array");
|
|
3277
|
+
}
|
|
3278
|
+
for (const v of vectors) {
|
|
3279
|
+
requireVector(v, "Each vector");
|
|
3280
|
+
}
|
|
3281
|
+
return backend.multiQuerySearchIds(collection, vectors, options);
|
|
3282
|
+
}
|
|
2865
3283
|
function trainPq2(backend, collection, options) {
|
|
2866
3284
|
return backend.trainPq(collection, options);
|
|
2867
3285
|
}
|
|
3286
|
+
function enableStreaming2(backend, collection, config) {
|
|
3287
|
+
return backend.enableStreaming(collection, config);
|
|
3288
|
+
}
|
|
2868
3289
|
function streamInsert2(backend, config, collection, docs) {
|
|
2869
3290
|
validateDocsBatch(docs, (doc) => {
|
|
2870
3291
|
validateDocument(doc, config);
|
|
@@ -3003,6 +3424,40 @@ function graphSearch2(backend, collection, request2) {
|
|
|
3003
3424
|
requireNonEmptyString(collection, "Collection");
|
|
3004
3425
|
return backend.graphSearch(collection, request2);
|
|
3005
3426
|
}
|
|
3427
|
+
function relate2(backend, collection, req) {
|
|
3428
|
+
requireNonEmptyString(collection, "Collection");
|
|
3429
|
+
if (!req.relType || typeof req.relType !== "string") {
|
|
3430
|
+
throw new ValidationError("Relation type is required and must be a string");
|
|
3431
|
+
}
|
|
3432
|
+
if (!isGraphNodeId(req.source) || !isGraphNodeId(req.target)) {
|
|
3433
|
+
throw new ValidationError("Source and target must be numbers or strings");
|
|
3434
|
+
}
|
|
3435
|
+
return backend.relate(collection, req);
|
|
3436
|
+
}
|
|
3437
|
+
function unrelate2(backend, collection, edgeId) {
|
|
3438
|
+
requireNonEmptyString(collection, "Collection");
|
|
3439
|
+
if (!isGraphNodeId(edgeId)) {
|
|
3440
|
+
throw new ValidationError("Edge ID must be a number or string");
|
|
3441
|
+
}
|
|
3442
|
+
return backend.unrelate(collection, edgeId);
|
|
3443
|
+
}
|
|
3444
|
+
function getRelations2(backend, collection, pointId) {
|
|
3445
|
+
requireNonEmptyString(collection, "Collection");
|
|
3446
|
+
if (!isGraphNodeId(pointId)) {
|
|
3447
|
+
throw new ValidationError("Point ID must be a number or string");
|
|
3448
|
+
}
|
|
3449
|
+
return backend.getRelations(collection, pointId);
|
|
3450
|
+
}
|
|
3451
|
+
function setTtlDurable2(backend, collection, pointId, ttlSeconds) {
|
|
3452
|
+
requireNonEmptyString(collection, "Collection");
|
|
3453
|
+
if (!isGraphNodeId(pointId)) {
|
|
3454
|
+
throw new ValidationError("Point ID must be a number or string");
|
|
3455
|
+
}
|
|
3456
|
+
if (typeof ttlSeconds !== "number" || ttlSeconds < 0) {
|
|
3457
|
+
throw new ValidationError("ttlSeconds must be a non-negative number");
|
|
3458
|
+
}
|
|
3459
|
+
return backend.setTtlDurable(collection, pointId, ttlSeconds);
|
|
3460
|
+
}
|
|
3006
3461
|
|
|
3007
3462
|
// src/client.ts
|
|
3008
3463
|
var VelesDB = class {
|
|
@@ -3099,6 +3554,24 @@ var VelesDB = class {
|
|
|
3099
3554
|
});
|
|
3100
3555
|
await this.backend.upsertBatch(collection, docs);
|
|
3101
3556
|
}
|
|
3557
|
+
/**
|
|
3558
|
+
* Bulk upsert via the binary wire format (REST backend only).
|
|
3559
|
+
*
|
|
3560
|
+
* Encodes `(id, vector)` pairs into the deterministic VRB1 binary layout
|
|
3561
|
+
* and sends them as a single `application/octet-stream` request, avoiding
|
|
3562
|
+
* per-point JSON overhead. Payloads are not carried — use
|
|
3563
|
+
* {@link upsertBatch} when you need them. Throws a not-supported error on
|
|
3564
|
+
* the WASM backend.
|
|
3565
|
+
*
|
|
3566
|
+
* @returns the number of points the server reports as inserted.
|
|
3567
|
+
*/
|
|
3568
|
+
async upsertBatchRaw(collection, docs) {
|
|
3569
|
+
this.ensureInitialized();
|
|
3570
|
+
validateDocsBatch(docs, (doc) => {
|
|
3571
|
+
validateDocument(doc, this.config);
|
|
3572
|
+
});
|
|
3573
|
+
return this.backend.upsertBatchRaw(collection, docs);
|
|
3574
|
+
}
|
|
3102
3575
|
async delete(collection, id) {
|
|
3103
3576
|
this.ensureInitialized();
|
|
3104
3577
|
validateRestPointId(id, this.config);
|
|
@@ -3146,6 +3619,11 @@ var VelesDB = class {
|
|
|
3146
3619
|
this.ensureInitialized();
|
|
3147
3620
|
return multiQuerySearch2(this.backend, collection, vectors, options);
|
|
3148
3621
|
}
|
|
3622
|
+
/** Multi-query fusion search returning only IDs and scores (no payloads). */
|
|
3623
|
+
async multiQuerySearchIds(collection, vectors, options) {
|
|
3624
|
+
this.ensureInitialized();
|
|
3625
|
+
return multiQuerySearchIds2(this.backend, collection, vectors, options);
|
|
3626
|
+
}
|
|
3149
3627
|
/**
|
|
3150
3628
|
* Pure sparse search against a named sparse index.
|
|
3151
3629
|
*
|
|
@@ -3176,6 +3654,10 @@ var VelesDB = class {
|
|
|
3176
3654
|
this.ensureInitialized();
|
|
3177
3655
|
return trainPq2(this.backend, collection, options);
|
|
3178
3656
|
}
|
|
3657
|
+
async enableStreaming(collection, config) {
|
|
3658
|
+
this.ensureInitialized();
|
|
3659
|
+
return enableStreaming2(this.backend, collection, config);
|
|
3660
|
+
}
|
|
3179
3661
|
async streamInsert(collection, docs) {
|
|
3180
3662
|
this.ensureInitialized();
|
|
3181
3663
|
return streamInsert2(this.backend, this.config, collection, docs);
|
|
@@ -3300,6 +3782,22 @@ var VelesDB = class {
|
|
|
3300
3782
|
this.ensureInitialized();
|
|
3301
3783
|
return graphSearch2(this.backend, collection, request2);
|
|
3302
3784
|
}
|
|
3785
|
+
async relate(collection, req) {
|
|
3786
|
+
this.ensureInitialized();
|
|
3787
|
+
return relate2(this.backend, collection, req);
|
|
3788
|
+
}
|
|
3789
|
+
async unrelate(collection, edgeId) {
|
|
3790
|
+
this.ensureInitialized();
|
|
3791
|
+
return unrelate2(this.backend, collection, edgeId);
|
|
3792
|
+
}
|
|
3793
|
+
async getRelations(collection, pointId) {
|
|
3794
|
+
this.ensureInitialized();
|
|
3795
|
+
return getRelations2(this.backend, collection, pointId);
|
|
3796
|
+
}
|
|
3797
|
+
async setTtlDurable(collection, pointId, ttlSeconds) {
|
|
3798
|
+
this.ensureInitialized();
|
|
3799
|
+
return setTtlDurable2(this.backend, collection, pointId, ttlSeconds);
|
|
3800
|
+
}
|
|
3303
3801
|
// ========================================================================
|
|
3304
3802
|
// Capabilities & Backend Info
|
|
3305
3803
|
// ========================================================================
|