@wiscale/velesdb-sdk 1.18.0 → 2.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 +110 -9
- package/dist/index.d.mts +170 -33
- package/dist/index.d.ts +170 -33
- package/dist/index.js +330 -51
- package/dist/index.mjs +330 -51
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -199,7 +199,7 @@ var WASM_CAPABILITIES = Object.freeze({
|
|
|
199
199
|
agentMemory: false,
|
|
200
200
|
streamInsert: false,
|
|
201
201
|
pqTraining: false,
|
|
202
|
-
velesqlQuery:
|
|
202
|
+
velesqlQuery: false,
|
|
203
203
|
collectionIntrospection: false
|
|
204
204
|
});
|
|
205
205
|
|
|
@@ -437,20 +437,47 @@ async function wasmMultiQuerySearch(ctx, collectionName, vectors, options) {
|
|
|
437
437
|
);
|
|
438
438
|
return raw.map((r) => mapWasmResult(ctx, collection, r));
|
|
439
439
|
}
|
|
440
|
-
|
|
440
|
+
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;
|
|
441
|
+
function parsePureNearQuery(queryString) {
|
|
442
|
+
const match = PURE_NEAR_QUERY.exec(queryString);
|
|
443
|
+
if (!match) {
|
|
444
|
+
throw new VelesDBError(
|
|
445
|
+
`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}`,
|
|
446
|
+
"NOT_SUPPORTED"
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
const parsed = { from: match[1], param: match[2] };
|
|
450
|
+
if (match[3] !== void 0) {
|
|
451
|
+
parsed.limit = Number(match[3]);
|
|
452
|
+
}
|
|
453
|
+
return parsed;
|
|
454
|
+
}
|
|
455
|
+
function resolveQueryK(limit, requestedK) {
|
|
456
|
+
if (limit !== void 0) {
|
|
457
|
+
return limit;
|
|
458
|
+
}
|
|
459
|
+
return typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
|
|
460
|
+
}
|
|
461
|
+
async function wasmQuery(ctx, collectionName, queryString, params, _options) {
|
|
441
462
|
const collection = ctx.getCollection(collectionName);
|
|
442
463
|
if (!collection) {
|
|
443
464
|
throw new NotFoundError(`Collection '${collectionName}'`);
|
|
444
465
|
}
|
|
445
|
-
const
|
|
466
|
+
const parsed = parsePureNearQuery(queryString);
|
|
467
|
+
if (parsed.from !== collectionName) {
|
|
468
|
+
throw new VelesDBError(
|
|
469
|
+
`Query targets collection '${parsed.from}' but was executed against '${collectionName}'.`,
|
|
470
|
+
"BAD_REQUEST"
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
const paramsVector = params?.[parsed.param];
|
|
446
474
|
if (!Array.isArray(paramsVector) && !(paramsVector instanceof Float32Array)) {
|
|
447
475
|
throw new VelesDBError(
|
|
448
|
-
|
|
476
|
+
`WASM query() expects params.${parsed.param} to contain the query embedding vector.`,
|
|
449
477
|
"BAD_REQUEST"
|
|
450
478
|
);
|
|
451
479
|
}
|
|
452
|
-
const
|
|
453
|
-
const k = typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
|
|
480
|
+
const k = resolveQueryK(parsed.limit, params?.k);
|
|
454
481
|
const raw = collection.store.query(
|
|
455
482
|
paramsVector instanceof Float32Array ? paramsVector : new Float32Array(paramsVector),
|
|
456
483
|
k
|
|
@@ -950,6 +977,12 @@ async function wasmRecordEpisodicEvent(_collection, _event) {
|
|
|
950
977
|
async function wasmRecallEpisodicEvents(_collection, _embedding, _k) {
|
|
951
978
|
wasmNotSupported("Agent memory");
|
|
952
979
|
}
|
|
980
|
+
async function wasmRecallRecentEvents(_collection, _since) {
|
|
981
|
+
wasmNotSupported("Agent memory");
|
|
982
|
+
}
|
|
983
|
+
async function wasmRecallOlderThanEvents(_collection, _before) {
|
|
984
|
+
wasmNotSupported("Agent memory");
|
|
985
|
+
}
|
|
953
986
|
async function wasmStoreProceduralPattern(_collection, _pattern) {
|
|
954
987
|
wasmNotSupported("Agent memory");
|
|
955
988
|
}
|
|
@@ -997,6 +1030,18 @@ function wasmUpsertNodePayload(_c, _id, _p) {
|
|
|
997
1030
|
function wasmGraphSearch(_c, _r) {
|
|
998
1031
|
return Promise.resolve(wasmNotSupported("Graph search"));
|
|
999
1032
|
}
|
|
1033
|
+
function wasmRelate(_c, _req) {
|
|
1034
|
+
return Promise.resolve(wasmNotSupported("Relation edges"));
|
|
1035
|
+
}
|
|
1036
|
+
function wasmUnrelate(_c, _id) {
|
|
1037
|
+
return Promise.resolve(wasmNotSupported("Relation edge removal"));
|
|
1038
|
+
}
|
|
1039
|
+
function wasmGetRelations(_c, _id) {
|
|
1040
|
+
return Promise.resolve(wasmNotSupported("Relation edges"));
|
|
1041
|
+
}
|
|
1042
|
+
function wasmSetTtlDurable(_c, _id, _ttl) {
|
|
1043
|
+
return Promise.resolve(wasmNotSupported("Durable TTL"));
|
|
1044
|
+
}
|
|
1000
1045
|
|
|
1001
1046
|
// src/backends/wasm.ts
|
|
1002
1047
|
var WasmBackend = class {
|
|
@@ -1351,6 +1396,14 @@ var WasmBackend = class {
|
|
|
1351
1396
|
this.ensureInitialized();
|
|
1352
1397
|
return wasmRecallEpisodicEvents(c, e, k);
|
|
1353
1398
|
}
|
|
1399
|
+
async recallRecentEvents(c, since) {
|
|
1400
|
+
this.ensureInitialized();
|
|
1401
|
+
return wasmRecallRecentEvents(c, since);
|
|
1402
|
+
}
|
|
1403
|
+
async recallOlderThanEvents(c, before) {
|
|
1404
|
+
this.ensureInitialized();
|
|
1405
|
+
return wasmRecallOlderThanEvents(c, before);
|
|
1406
|
+
}
|
|
1354
1407
|
async storeProceduralPattern(c, p) {
|
|
1355
1408
|
this.ensureInitialized();
|
|
1356
1409
|
return wasmStoreProceduralPattern(c, p);
|
|
@@ -1412,16 +1465,43 @@ var WasmBackend = class {
|
|
|
1412
1465
|
this.ensureInitialized();
|
|
1413
1466
|
return wasmSparseSearchNamed(c, q, idx, o);
|
|
1414
1467
|
}
|
|
1468
|
+
async relate(c, req) {
|
|
1469
|
+
this.ensureInitialized();
|
|
1470
|
+
return wasmRelate(c, req);
|
|
1471
|
+
}
|
|
1472
|
+
async unrelate(c, edgeId) {
|
|
1473
|
+
this.ensureInitialized();
|
|
1474
|
+
return wasmUnrelate(c, edgeId);
|
|
1475
|
+
}
|
|
1476
|
+
async getRelations(c, pointId) {
|
|
1477
|
+
this.ensureInitialized();
|
|
1478
|
+
return wasmGetRelations(c, pointId);
|
|
1479
|
+
}
|
|
1480
|
+
async setTtlDurable(c, pointId, ttlSeconds) {
|
|
1481
|
+
this.ensureInitialized();
|
|
1482
|
+
return wasmSetTtlDurable(c, pointId, ttlSeconds);
|
|
1483
|
+
}
|
|
1415
1484
|
};
|
|
1416
1485
|
|
|
1417
1486
|
// src/backends/crud-backend.ts
|
|
1487
|
+
var U64_MAX = 18446744073709551615n;
|
|
1488
|
+
function coerceDecimalStringId(id) {
|
|
1489
|
+
if (!/^\d+$/.test(id)) return NaN;
|
|
1490
|
+
const big = BigInt(id);
|
|
1491
|
+
if (big > U64_MAX) return NaN;
|
|
1492
|
+
return big > BigInt(Number.MAX_SAFE_INTEGER) ? id : Number(id);
|
|
1493
|
+
}
|
|
1418
1494
|
function parseRestPointId(id) {
|
|
1419
|
-
|
|
1495
|
+
const coerced = typeof id === "string" ? coerceDecimalStringId(id) : id;
|
|
1496
|
+
if (typeof coerced === "string") {
|
|
1497
|
+
return coerced;
|
|
1498
|
+
}
|
|
1499
|
+
if (!Number.isFinite(coerced) || coerced < 0 || !Number.isInteger(coerced) || coerced > Number.MAX_SAFE_INTEGER) {
|
|
1420
1500
|
throw new ValidationError(
|
|
1421
|
-
`REST backend requires numeric u64-compatible IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER}). Received: ${String(id)}`
|
|
1501
|
+
`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
1502
|
);
|
|
1423
1503
|
}
|
|
1424
|
-
return
|
|
1504
|
+
return coerced;
|
|
1425
1505
|
}
|
|
1426
1506
|
function sparseVectorToRestFormat(sv) {
|
|
1427
1507
|
const result = {};
|
|
@@ -1876,6 +1956,31 @@ async function graphSearch(transport, collection, request2) {
|
|
|
1876
1956
|
return { results: items };
|
|
1877
1957
|
}
|
|
1878
1958
|
|
|
1959
|
+
// src/backends/scroll-backend.ts
|
|
1960
|
+
async function scroll(transport, collection, request2) {
|
|
1961
|
+
const body = {};
|
|
1962
|
+
if (request2?.cursor !== void 0) {
|
|
1963
|
+
body.cursor = request2.cursor;
|
|
1964
|
+
}
|
|
1965
|
+
if (request2?.batchSize !== void 0) {
|
|
1966
|
+
body.batch_size = request2.batchSize;
|
|
1967
|
+
}
|
|
1968
|
+
if (request2?.filter !== void 0) {
|
|
1969
|
+
body.filter = request2.filter;
|
|
1970
|
+
}
|
|
1971
|
+
const response = await transport.requestJson(
|
|
1972
|
+
"POST",
|
|
1973
|
+
`${collectionPath(collection)}/points/scroll`,
|
|
1974
|
+
body
|
|
1975
|
+
);
|
|
1976
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
1977
|
+
const data = response.data;
|
|
1978
|
+
return {
|
|
1979
|
+
points: data.points,
|
|
1980
|
+
nextCursor: data.next_cursor
|
|
1981
|
+
};
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1879
1984
|
// src/backends/agent-memory-backend.ts
|
|
1880
1985
|
var _idCounter = 0;
|
|
1881
1986
|
var _lastTimestamp = 0;
|
|
@@ -1893,20 +1998,28 @@ function generateUniqueId() {
|
|
|
1893
1998
|
}
|
|
1894
1999
|
return _lastTimestamp * 1e3 + _idCounter;
|
|
1895
2000
|
}
|
|
2001
|
+
function memoryIdToString(id) {
|
|
2002
|
+
return String(id);
|
|
2003
|
+
}
|
|
2004
|
+
function nowUnixSeconds() {
|
|
2005
|
+
return Math.floor(Date.now() / 1e3);
|
|
2006
|
+
}
|
|
1896
2007
|
async function storeSemanticFact(transport, collection, entry) {
|
|
1897
2008
|
const response = await transport.requestJson(
|
|
1898
2009
|
"POST",
|
|
1899
2010
|
`${collectionPath(collection)}/points`,
|
|
1900
2011
|
{
|
|
1901
2012
|
points: [{
|
|
1902
|
-
id: entry.id,
|
|
2013
|
+
id: parseRestPointId(entry.id),
|
|
1903
2014
|
vector: entry.embedding,
|
|
1904
2015
|
payload: {
|
|
1905
2016
|
// Caller metadata is spread first so the reserved keys below
|
|
1906
|
-
// (`_memory_type`, `
|
|
2017
|
+
// (`_memory_type`, `content`) always win and cannot be clobbered.
|
|
1907
2018
|
...entry.metadata,
|
|
1908
2019
|
_memory_type: "semantic",
|
|
1909
|
-
|
|
2020
|
+
// `content` matches the core semantic store and the server/Python
|
|
2021
|
+
// payload field (BREAKING: was `text` before this change).
|
|
2022
|
+
content: entry.text
|
|
1910
2023
|
}
|
|
1911
2024
|
}]
|
|
1912
2025
|
}
|
|
@@ -1917,7 +2030,8 @@ async function searchSemanticMemory(transport, collection, embedding, k = 5) {
|
|
|
1917
2030
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "semantic" });
|
|
1918
2031
|
}
|
|
1919
2032
|
async function recordEpisodicEvent(transport, collection, event) {
|
|
1920
|
-
const id = generateUniqueId();
|
|
2033
|
+
const id = event.id !== void 0 ? parseRestPointId(event.id) : generateUniqueId();
|
|
2034
|
+
const timestamp = event.timestamp ?? nowUnixSeconds();
|
|
1921
2035
|
const response = await transport.requestJson(
|
|
1922
2036
|
"POST",
|
|
1923
2037
|
`${collectionPath(collection)}/points`,
|
|
@@ -1933,19 +2047,21 @@ async function recordEpisodicEvent(transport, collection, event) {
|
|
|
1933
2047
|
...event.metadata,
|
|
1934
2048
|
_memory_type: "episodic",
|
|
1935
2049
|
event_type: event.eventType,
|
|
1936
|
-
|
|
2050
|
+
// NUMERIC unix-seconds, mirroring the core episodic store so
|
|
2051
|
+
// recallRecent/recallOlderThan can range-filter on it.
|
|
2052
|
+
timestamp
|
|
1937
2053
|
}
|
|
1938
2054
|
}]
|
|
1939
2055
|
}
|
|
1940
2056
|
);
|
|
1941
2057
|
throwOnError(response);
|
|
1942
|
-
return id;
|
|
2058
|
+
return memoryIdToString(id);
|
|
1943
2059
|
}
|
|
1944
2060
|
async function recallEpisodicEvents(transport, collection, embedding, k = 5) {
|
|
1945
2061
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "episodic" });
|
|
1946
2062
|
}
|
|
1947
2063
|
async function storeProceduralPattern(transport, collection, pattern) {
|
|
1948
|
-
const id = generateUniqueId();
|
|
2064
|
+
const id = pattern.id !== void 0 ? parseRestPointId(pattern.id) : generateUniqueId();
|
|
1949
2065
|
const response = await transport.requestJson(
|
|
1950
2066
|
"POST",
|
|
1951
2067
|
`${collectionPath(collection)}/points`,
|
|
@@ -1966,11 +2082,41 @@ async function storeProceduralPattern(transport, collection, pattern) {
|
|
|
1966
2082
|
}
|
|
1967
2083
|
);
|
|
1968
2084
|
throwOnError(response);
|
|
1969
|
-
return id;
|
|
2085
|
+
return memoryIdToString(id);
|
|
1970
2086
|
}
|
|
1971
2087
|
async function matchProceduralPatterns(transport, collection, embedding, k = 5) {
|
|
1972
2088
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "procedural" });
|
|
1973
2089
|
}
|
|
2090
|
+
function toEpisodicRecord(point) {
|
|
2091
|
+
const payload = point.payload ?? {};
|
|
2092
|
+
if (payload._memory_type !== "episodic") return void 0;
|
|
2093
|
+
if (typeof payload.timestamp !== "number") return void 0;
|
|
2094
|
+
return { id: String(point.id), timestamp: payload.timestamp, payload };
|
|
2095
|
+
}
|
|
2096
|
+
async function scrollEpisodicRecords(transport, collection) {
|
|
2097
|
+
const records = [];
|
|
2098
|
+
let cursor = null;
|
|
2099
|
+
do {
|
|
2100
|
+
const page = await scroll(transport, collection, {
|
|
2101
|
+
cursor: cursor ?? void 0,
|
|
2102
|
+
filter: { _memory_type: "episodic" }
|
|
2103
|
+
});
|
|
2104
|
+
for (const point of page.points) {
|
|
2105
|
+
const record = toEpisodicRecord(point);
|
|
2106
|
+
if (record !== void 0) records.push(record);
|
|
2107
|
+
}
|
|
2108
|
+
cursor = page.nextCursor;
|
|
2109
|
+
} while (cursor !== null && cursor !== void 0);
|
|
2110
|
+
return records;
|
|
2111
|
+
}
|
|
2112
|
+
async function recallRecentEvents(transport, collection, since) {
|
|
2113
|
+
const records = await scrollEpisodicRecords(transport, collection);
|
|
2114
|
+
return records.filter((r) => since === void 0 || r.timestamp >= since).sort((a, b) => b.timestamp - a.timestamp);
|
|
2115
|
+
}
|
|
2116
|
+
async function recallOlderThanEvents(transport, collection, before) {
|
|
2117
|
+
const records = await scrollEpisodicRecords(transport, collection);
|
|
2118
|
+
return records.filter((r) => r.timestamp < before).sort((a, b) => b.timestamp - a.timestamp);
|
|
2119
|
+
}
|
|
1974
2120
|
|
|
1975
2121
|
// src/search-quality.ts
|
|
1976
2122
|
function searchQualityToMode(quality) {
|
|
@@ -2203,6 +2349,64 @@ async function traverseParallel(transport, collection, request2) {
|
|
|
2203
2349
|
throwOnError(response, `Collection '${collection}'`);
|
|
2204
2350
|
return toTraverseResponse(response.data);
|
|
2205
2351
|
}
|
|
2352
|
+
async function relate(transport, collection, req) {
|
|
2353
|
+
const response = await transport.requestJson(
|
|
2354
|
+
"POST",
|
|
2355
|
+
`${collectionPath(collection)}/relations`,
|
|
2356
|
+
{
|
|
2357
|
+
source: req.source,
|
|
2358
|
+
target: req.target,
|
|
2359
|
+
rel_type: req.relType,
|
|
2360
|
+
properties: req.properties ?? {}
|
|
2361
|
+
}
|
|
2362
|
+
);
|
|
2363
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2364
|
+
return { edgeId: response.data.edge_id };
|
|
2365
|
+
}
|
|
2366
|
+
async function unrelate(transport, collection, edgeId) {
|
|
2367
|
+
const response = await transport.requestJson(
|
|
2368
|
+
"DELETE",
|
|
2369
|
+
`${collectionPath(collection)}/relations/${encodeURIComponent(String(edgeId))}`
|
|
2370
|
+
);
|
|
2371
|
+
if (response.error !== void 0) {
|
|
2372
|
+
const { code, message } = response.error;
|
|
2373
|
+
const err = parseVelesError(code, message);
|
|
2374
|
+
if (err instanceof EdgeNotFoundError) {
|
|
2375
|
+
return false;
|
|
2376
|
+
}
|
|
2377
|
+
if (code === "NOT_FOUND") {
|
|
2378
|
+
return false;
|
|
2379
|
+
}
|
|
2380
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2381
|
+
}
|
|
2382
|
+
return true;
|
|
2383
|
+
}
|
|
2384
|
+
async function getRelations(transport, collection, pointId) {
|
|
2385
|
+
const response = await transport.requestJson(
|
|
2386
|
+
"GET",
|
|
2387
|
+
`${collectionPath(collection)}/points/${encodeURIComponent(String(pointId))}/relations`
|
|
2388
|
+
);
|
|
2389
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2390
|
+
const raw = response.data;
|
|
2391
|
+
return {
|
|
2392
|
+
edges: raw.edges.map((e) => ({
|
|
2393
|
+
id: e.id,
|
|
2394
|
+
source: e.source,
|
|
2395
|
+
target: e.target,
|
|
2396
|
+
relType: e.rel_type,
|
|
2397
|
+
properties: e.properties
|
|
2398
|
+
})),
|
|
2399
|
+
count: raw.count
|
|
2400
|
+
};
|
|
2401
|
+
}
|
|
2402
|
+
async function setTtlDurable(transport, collection, pointId, ttlSeconds) {
|
|
2403
|
+
const response = await transport.requestJson(
|
|
2404
|
+
"PATCH",
|
|
2405
|
+
`${collectionPath(collection)}/points/${encodeURIComponent(String(pointId))}/ttl`,
|
|
2406
|
+
{ ttl_seconds: ttlSeconds }
|
|
2407
|
+
);
|
|
2408
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2409
|
+
}
|
|
2206
2410
|
|
|
2207
2411
|
// src/backends/query-backend.ts
|
|
2208
2412
|
function isLikelyAggregationQuery(queryString) {
|
|
@@ -2335,31 +2539,6 @@ async function collectionSanity(transport, collection) {
|
|
|
2335
2539
|
};
|
|
2336
2540
|
}
|
|
2337
2541
|
|
|
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
2542
|
// src/backends/admin-backend.ts
|
|
2364
2543
|
function mapStatsResponse(data) {
|
|
2365
2544
|
let columnStats;
|
|
@@ -2545,9 +2724,17 @@ async function streamInsert(transport, collection, docs) {
|
|
|
2545
2724
|
}
|
|
2546
2725
|
}
|
|
2547
2726
|
}
|
|
2727
|
+
function requireSafeRangeId(restId) {
|
|
2728
|
+
if (typeof restId === "string") {
|
|
2729
|
+
throw new ValidationError(
|
|
2730
|
+
`streamUpsertPoints requires ids in the JS safe integer range (0..${Number.MAX_SAFE_INTEGER}); use upsert/upsertBatch for string ids above it. Received: ${restId}`
|
|
2731
|
+
);
|
|
2732
|
+
}
|
|
2733
|
+
return restId;
|
|
2734
|
+
}
|
|
2548
2735
|
async function streamUpsertPoints(transport, collection, docs) {
|
|
2549
2736
|
const ndjsonLines = docs.map((doc) => {
|
|
2550
|
-
const restId = transport.parseRestPointId(doc.id);
|
|
2737
|
+
const restId = requireSafeRangeId(transport.parseRestPointId(doc.id));
|
|
2551
2738
|
const vector = toNumberArray(doc.vector);
|
|
2552
2739
|
const point = {
|
|
2553
2740
|
id: restId,
|
|
@@ -2738,6 +2925,22 @@ var RestBackend = class {
|
|
|
2738
2925
|
this.ensureInitialized();
|
|
2739
2926
|
return graphSearch(buildBaseTransport(this.httpConfig), c, r);
|
|
2740
2927
|
}
|
|
2928
|
+
async relate(c, req) {
|
|
2929
|
+
this.ensureInitialized();
|
|
2930
|
+
return relate(buildCrudTransport(this.httpConfig), c, req);
|
|
2931
|
+
}
|
|
2932
|
+
async unrelate(c, edgeId) {
|
|
2933
|
+
this.ensureInitialized();
|
|
2934
|
+
return unrelate(buildCrudTransport(this.httpConfig), c, edgeId);
|
|
2935
|
+
}
|
|
2936
|
+
async getRelations(c, pointId) {
|
|
2937
|
+
this.ensureInitialized();
|
|
2938
|
+
return getRelations(buildCrudTransport(this.httpConfig), c, pointId);
|
|
2939
|
+
}
|
|
2940
|
+
async setTtlDurable(c, pointId, ttlSeconds) {
|
|
2941
|
+
this.ensureInitialized();
|
|
2942
|
+
return setTtlDurable(buildCrudTransport(this.httpConfig), c, pointId, ttlSeconds);
|
|
2943
|
+
}
|
|
2741
2944
|
// Search
|
|
2742
2945
|
async search(c, q, o) {
|
|
2743
2946
|
this.ensureInitialized();
|
|
@@ -2870,6 +3073,14 @@ var RestBackend = class {
|
|
|
2870
3073
|
this.ensureInitialized();
|
|
2871
3074
|
return recallEpisodicEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, e, k);
|
|
2872
3075
|
}
|
|
3076
|
+
async recallRecentEvents(c, since) {
|
|
3077
|
+
this.ensureInitialized();
|
|
3078
|
+
return recallRecentEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, since);
|
|
3079
|
+
}
|
|
3080
|
+
async recallOlderThanEvents(c, before) {
|
|
3081
|
+
this.ensureInitialized();
|
|
3082
|
+
return recallOlderThanEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, before);
|
|
3083
|
+
}
|
|
2873
3084
|
async storeProceduralPattern(c, p) {
|
|
2874
3085
|
this.ensureInitialized();
|
|
2875
3086
|
return storeProceduralPattern(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, p);
|
|
@@ -2907,15 +3118,29 @@ var AgentMemoryClient = class {
|
|
|
2907
3118
|
async searchFacts(collection, embedding, k = 5) {
|
|
2908
3119
|
return this.backend.searchSemanticMemory(collection, embedding, k);
|
|
2909
3120
|
}
|
|
2910
|
-
/** Record an episodic event. Returns the
|
|
3121
|
+
/** Record an episodic event. Returns the point ID (string, u64-safe). */
|
|
2911
3122
|
async recordEvent(collection, event) {
|
|
2912
3123
|
return this.backend.recordEpisodicEvent(collection, event);
|
|
2913
3124
|
}
|
|
2914
|
-
/** Recall episodic events */
|
|
3125
|
+
/** Recall episodic events by vector similarity. */
|
|
2915
3126
|
async recallEvents(collection, embedding, k = 5) {
|
|
2916
3127
|
return this.backend.recallEpisodicEvents(collection, embedding, k);
|
|
2917
3128
|
}
|
|
2918
|
-
/**
|
|
3129
|
+
/**
|
|
3130
|
+
* Recall episodic events most-recent-first, optionally bounded below by
|
|
3131
|
+
* `since` (inclusive unix-seconds). Mirrors core `episodic.recent(since)`.
|
|
3132
|
+
*/
|
|
3133
|
+
async recallRecent(collection, since) {
|
|
3134
|
+
return this.backend.recallRecentEvents(collection, since);
|
|
3135
|
+
}
|
|
3136
|
+
/**
|
|
3137
|
+
* Recall episodic events strictly older than `before` (unix-seconds),
|
|
3138
|
+
* most-recent-first. Mirrors core `episodic.older_than(before)`.
|
|
3139
|
+
*/
|
|
3140
|
+
async recallOlderThan(collection, before) {
|
|
3141
|
+
return this.backend.recallOlderThanEvents(collection, before);
|
|
3142
|
+
}
|
|
3143
|
+
/** Store a procedural pattern. Returns the point ID (string, u64-safe). */
|
|
2919
3144
|
async learnProcedure(collection, pattern) {
|
|
2920
3145
|
return this.backend.storeProceduralPattern(collection, pattern);
|
|
2921
3146
|
}
|
|
@@ -2923,7 +3148,12 @@ var AgentMemoryClient = class {
|
|
|
2923
3148
|
async recallProcedures(collection, embedding, k = 5) {
|
|
2924
3149
|
return this.backend.matchProceduralPatterns(collection, embedding, k);
|
|
2925
3150
|
}
|
|
2926
|
-
/**
|
|
3151
|
+
/**
|
|
3152
|
+
* Delete a memory entry (fact, event, or procedure) by its point ID.
|
|
3153
|
+
*
|
|
3154
|
+
* Accepts the `string` ids returned by `recordEvent` / `learnProcedure`
|
|
3155
|
+
* (u64-safe decimal strings) as well as numeric ids.
|
|
3156
|
+
*/
|
|
2927
3157
|
async deleteMemory(collection, id) {
|
|
2928
3158
|
return this.backend.delete(collection, id);
|
|
2929
3159
|
}
|
|
@@ -2957,11 +3187,10 @@ function validateDocument(doc, config) {
|
|
|
2957
3187
|
validateRestPointId(doc.id, config);
|
|
2958
3188
|
}
|
|
2959
3189
|
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
|
-
);
|
|
3190
|
+
if (config.backend !== "rest") {
|
|
3191
|
+
return;
|
|
2964
3192
|
}
|
|
3193
|
+
parseRestPointId(id);
|
|
2965
3194
|
}
|
|
2966
3195
|
|
|
2967
3196
|
// src/client/search-methods.ts
|
|
@@ -3142,6 +3371,40 @@ function graphSearch2(backend, collection, request2) {
|
|
|
3142
3371
|
requireNonEmptyString(collection, "Collection");
|
|
3143
3372
|
return backend.graphSearch(collection, request2);
|
|
3144
3373
|
}
|
|
3374
|
+
function relate2(backend, collection, req) {
|
|
3375
|
+
requireNonEmptyString(collection, "Collection");
|
|
3376
|
+
if (!req.relType || typeof req.relType !== "string") {
|
|
3377
|
+
throw new ValidationError("Relation type is required and must be a string");
|
|
3378
|
+
}
|
|
3379
|
+
if (!isGraphNodeId(req.source) || !isGraphNodeId(req.target)) {
|
|
3380
|
+
throw new ValidationError("Source and target must be numbers or strings");
|
|
3381
|
+
}
|
|
3382
|
+
return backend.relate(collection, req);
|
|
3383
|
+
}
|
|
3384
|
+
function unrelate2(backend, collection, edgeId) {
|
|
3385
|
+
requireNonEmptyString(collection, "Collection");
|
|
3386
|
+
if (!isGraphNodeId(edgeId)) {
|
|
3387
|
+
throw new ValidationError("Edge ID must be a number or string");
|
|
3388
|
+
}
|
|
3389
|
+
return backend.unrelate(collection, edgeId);
|
|
3390
|
+
}
|
|
3391
|
+
function getRelations2(backend, collection, pointId) {
|
|
3392
|
+
requireNonEmptyString(collection, "Collection");
|
|
3393
|
+
if (!isGraphNodeId(pointId)) {
|
|
3394
|
+
throw new ValidationError("Point ID must be a number or string");
|
|
3395
|
+
}
|
|
3396
|
+
return backend.getRelations(collection, pointId);
|
|
3397
|
+
}
|
|
3398
|
+
function setTtlDurable2(backend, collection, pointId, ttlSeconds) {
|
|
3399
|
+
requireNonEmptyString(collection, "Collection");
|
|
3400
|
+
if (!isGraphNodeId(pointId)) {
|
|
3401
|
+
throw new ValidationError("Point ID must be a number or string");
|
|
3402
|
+
}
|
|
3403
|
+
if (typeof ttlSeconds !== "number" || ttlSeconds < 0) {
|
|
3404
|
+
throw new ValidationError("ttlSeconds must be a non-negative number");
|
|
3405
|
+
}
|
|
3406
|
+
return backend.setTtlDurable(collection, pointId, ttlSeconds);
|
|
3407
|
+
}
|
|
3145
3408
|
|
|
3146
3409
|
// src/client.ts
|
|
3147
3410
|
var VelesDB = class {
|
|
@@ -3439,6 +3702,22 @@ var VelesDB = class {
|
|
|
3439
3702
|
this.ensureInitialized();
|
|
3440
3703
|
return graphSearch2(this.backend, collection, request2);
|
|
3441
3704
|
}
|
|
3705
|
+
async relate(collection, req) {
|
|
3706
|
+
this.ensureInitialized();
|
|
3707
|
+
return relate2(this.backend, collection, req);
|
|
3708
|
+
}
|
|
3709
|
+
async unrelate(collection, edgeId) {
|
|
3710
|
+
this.ensureInitialized();
|
|
3711
|
+
return unrelate2(this.backend, collection, edgeId);
|
|
3712
|
+
}
|
|
3713
|
+
async getRelations(collection, pointId) {
|
|
3714
|
+
this.ensureInitialized();
|
|
3715
|
+
return getRelations2(this.backend, collection, pointId);
|
|
3716
|
+
}
|
|
3717
|
+
async setTtlDurable(collection, pointId, ttlSeconds) {
|
|
3718
|
+
this.ensureInitialized();
|
|
3719
|
+
return setTtlDurable2(this.backend, collection, pointId, ttlSeconds);
|
|
3720
|
+
}
|
|
3442
3721
|
// ========================================================================
|
|
3443
3722
|
// Capabilities & Backend Info
|
|
3444
3723
|
// ========================================================================
|