@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.mjs
CHANGED
|
@@ -60,7 +60,7 @@ var WASM_CAPABILITIES = Object.freeze({
|
|
|
60
60
|
agentMemory: false,
|
|
61
61
|
streamInsert: false,
|
|
62
62
|
pqTraining: false,
|
|
63
|
-
velesqlQuery:
|
|
63
|
+
velesqlQuery: false,
|
|
64
64
|
collectionIntrospection: false
|
|
65
65
|
});
|
|
66
66
|
|
|
@@ -298,20 +298,47 @@ async function wasmMultiQuerySearch(ctx, collectionName, vectors, options) {
|
|
|
298
298
|
);
|
|
299
299
|
return raw.map((r) => mapWasmResult(ctx, collection, r));
|
|
300
300
|
}
|
|
301
|
-
|
|
301
|
+
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;
|
|
302
|
+
function parsePureNearQuery(queryString) {
|
|
303
|
+
const match = PURE_NEAR_QUERY.exec(queryString);
|
|
304
|
+
if (!match) {
|
|
305
|
+
throw new VelesDBError(
|
|
306
|
+
`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}`,
|
|
307
|
+
"NOT_SUPPORTED"
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
const parsed = { from: match[1], param: match[2] };
|
|
311
|
+
if (match[3] !== void 0) {
|
|
312
|
+
parsed.limit = Number(match[3]);
|
|
313
|
+
}
|
|
314
|
+
return parsed;
|
|
315
|
+
}
|
|
316
|
+
function resolveQueryK(limit, requestedK) {
|
|
317
|
+
if (limit !== void 0) {
|
|
318
|
+
return limit;
|
|
319
|
+
}
|
|
320
|
+
return typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
|
|
321
|
+
}
|
|
322
|
+
async function wasmQuery(ctx, collectionName, queryString, params, _options) {
|
|
302
323
|
const collection = ctx.getCollection(collectionName);
|
|
303
324
|
if (!collection) {
|
|
304
325
|
throw new NotFoundError(`Collection '${collectionName}'`);
|
|
305
326
|
}
|
|
306
|
-
const
|
|
327
|
+
const parsed = parsePureNearQuery(queryString);
|
|
328
|
+
if (parsed.from !== collectionName) {
|
|
329
|
+
throw new VelesDBError(
|
|
330
|
+
`Query targets collection '${parsed.from}' but was executed against '${collectionName}'.`,
|
|
331
|
+
"BAD_REQUEST"
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
const paramsVector = params?.[parsed.param];
|
|
307
335
|
if (!Array.isArray(paramsVector) && !(paramsVector instanceof Float32Array)) {
|
|
308
336
|
throw new VelesDBError(
|
|
309
|
-
|
|
337
|
+
`WASM query() expects params.${parsed.param} to contain the query embedding vector.`,
|
|
310
338
|
"BAD_REQUEST"
|
|
311
339
|
);
|
|
312
340
|
}
|
|
313
|
-
const
|
|
314
|
-
const k = typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
|
|
341
|
+
const k = resolveQueryK(parsed.limit, params?.k);
|
|
315
342
|
const raw = collection.store.query(
|
|
316
343
|
paramsVector instanceof Float32Array ? paramsVector : new Float32Array(paramsVector),
|
|
317
344
|
k
|
|
@@ -811,6 +838,12 @@ async function wasmRecordEpisodicEvent(_collection, _event) {
|
|
|
811
838
|
async function wasmRecallEpisodicEvents(_collection, _embedding, _k) {
|
|
812
839
|
wasmNotSupported("Agent memory");
|
|
813
840
|
}
|
|
841
|
+
async function wasmRecallRecentEvents(_collection, _since) {
|
|
842
|
+
wasmNotSupported("Agent memory");
|
|
843
|
+
}
|
|
844
|
+
async function wasmRecallOlderThanEvents(_collection, _before) {
|
|
845
|
+
wasmNotSupported("Agent memory");
|
|
846
|
+
}
|
|
814
847
|
async function wasmStoreProceduralPattern(_collection, _pattern) {
|
|
815
848
|
wasmNotSupported("Agent memory");
|
|
816
849
|
}
|
|
@@ -858,6 +891,18 @@ function wasmUpsertNodePayload(_c, _id, _p) {
|
|
|
858
891
|
function wasmGraphSearch(_c, _r) {
|
|
859
892
|
return Promise.resolve(wasmNotSupported("Graph search"));
|
|
860
893
|
}
|
|
894
|
+
function wasmRelate(_c, _req) {
|
|
895
|
+
return Promise.resolve(wasmNotSupported("Relation edges"));
|
|
896
|
+
}
|
|
897
|
+
function wasmUnrelate(_c, _id) {
|
|
898
|
+
return Promise.resolve(wasmNotSupported("Relation edge removal"));
|
|
899
|
+
}
|
|
900
|
+
function wasmGetRelations(_c, _id) {
|
|
901
|
+
return Promise.resolve(wasmNotSupported("Relation edges"));
|
|
902
|
+
}
|
|
903
|
+
function wasmSetTtlDurable(_c, _id, _ttl) {
|
|
904
|
+
return Promise.resolve(wasmNotSupported("Durable TTL"));
|
|
905
|
+
}
|
|
861
906
|
|
|
862
907
|
// src/backends/wasm.ts
|
|
863
908
|
var WasmBackend = class {
|
|
@@ -1212,6 +1257,14 @@ var WasmBackend = class {
|
|
|
1212
1257
|
this.ensureInitialized();
|
|
1213
1258
|
return wasmRecallEpisodicEvents(c, e, k);
|
|
1214
1259
|
}
|
|
1260
|
+
async recallRecentEvents(c, since) {
|
|
1261
|
+
this.ensureInitialized();
|
|
1262
|
+
return wasmRecallRecentEvents(c, since);
|
|
1263
|
+
}
|
|
1264
|
+
async recallOlderThanEvents(c, before) {
|
|
1265
|
+
this.ensureInitialized();
|
|
1266
|
+
return wasmRecallOlderThanEvents(c, before);
|
|
1267
|
+
}
|
|
1215
1268
|
async storeProceduralPattern(c, p) {
|
|
1216
1269
|
this.ensureInitialized();
|
|
1217
1270
|
return wasmStoreProceduralPattern(c, p);
|
|
@@ -1273,16 +1326,43 @@ var WasmBackend = class {
|
|
|
1273
1326
|
this.ensureInitialized();
|
|
1274
1327
|
return wasmSparseSearchNamed(c, q, idx, o);
|
|
1275
1328
|
}
|
|
1329
|
+
async relate(c, req) {
|
|
1330
|
+
this.ensureInitialized();
|
|
1331
|
+
return wasmRelate(c, req);
|
|
1332
|
+
}
|
|
1333
|
+
async unrelate(c, edgeId) {
|
|
1334
|
+
this.ensureInitialized();
|
|
1335
|
+
return wasmUnrelate(c, edgeId);
|
|
1336
|
+
}
|
|
1337
|
+
async getRelations(c, pointId) {
|
|
1338
|
+
this.ensureInitialized();
|
|
1339
|
+
return wasmGetRelations(c, pointId);
|
|
1340
|
+
}
|
|
1341
|
+
async setTtlDurable(c, pointId, ttlSeconds) {
|
|
1342
|
+
this.ensureInitialized();
|
|
1343
|
+
return wasmSetTtlDurable(c, pointId, ttlSeconds);
|
|
1344
|
+
}
|
|
1276
1345
|
};
|
|
1277
1346
|
|
|
1278
1347
|
// src/backends/crud-backend.ts
|
|
1348
|
+
var U64_MAX = 18446744073709551615n;
|
|
1349
|
+
function coerceDecimalStringId(id) {
|
|
1350
|
+
if (!/^\d+$/.test(id)) return NaN;
|
|
1351
|
+
const big = BigInt(id);
|
|
1352
|
+
if (big > U64_MAX) return NaN;
|
|
1353
|
+
return big > BigInt(Number.MAX_SAFE_INTEGER) ? id : Number(id);
|
|
1354
|
+
}
|
|
1279
1355
|
function parseRestPointId(id) {
|
|
1280
|
-
|
|
1356
|
+
const coerced = typeof id === "string" ? coerceDecimalStringId(id) : id;
|
|
1357
|
+
if (typeof coerced === "string") {
|
|
1358
|
+
return coerced;
|
|
1359
|
+
}
|
|
1360
|
+
if (!Number.isFinite(coerced) || coerced < 0 || !Number.isInteger(coerced) || coerced > Number.MAX_SAFE_INTEGER) {
|
|
1281
1361
|
throw new ValidationError(
|
|
1282
|
-
`REST backend requires numeric u64-compatible IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER}). Received: ${String(id)}`
|
|
1362
|
+
`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
1363
|
);
|
|
1284
1364
|
}
|
|
1285
|
-
return
|
|
1365
|
+
return coerced;
|
|
1286
1366
|
}
|
|
1287
1367
|
function sparseVectorToRestFormat(sv) {
|
|
1288
1368
|
const result = {};
|
|
@@ -1737,6 +1817,31 @@ async function graphSearch(transport, collection, request2) {
|
|
|
1737
1817
|
return { results: items };
|
|
1738
1818
|
}
|
|
1739
1819
|
|
|
1820
|
+
// src/backends/scroll-backend.ts
|
|
1821
|
+
async function scroll(transport, collection, request2) {
|
|
1822
|
+
const body = {};
|
|
1823
|
+
if (request2?.cursor !== void 0) {
|
|
1824
|
+
body.cursor = request2.cursor;
|
|
1825
|
+
}
|
|
1826
|
+
if (request2?.batchSize !== void 0) {
|
|
1827
|
+
body.batch_size = request2.batchSize;
|
|
1828
|
+
}
|
|
1829
|
+
if (request2?.filter !== void 0) {
|
|
1830
|
+
body.filter = request2.filter;
|
|
1831
|
+
}
|
|
1832
|
+
const response = await transport.requestJson(
|
|
1833
|
+
"POST",
|
|
1834
|
+
`${collectionPath(collection)}/points/scroll`,
|
|
1835
|
+
body
|
|
1836
|
+
);
|
|
1837
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
1838
|
+
const data = response.data;
|
|
1839
|
+
return {
|
|
1840
|
+
points: data.points,
|
|
1841
|
+
nextCursor: data.next_cursor
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1740
1845
|
// src/backends/agent-memory-backend.ts
|
|
1741
1846
|
var _idCounter = 0;
|
|
1742
1847
|
var _lastTimestamp = 0;
|
|
@@ -1754,20 +1859,28 @@ function generateUniqueId() {
|
|
|
1754
1859
|
}
|
|
1755
1860
|
return _lastTimestamp * 1e3 + _idCounter;
|
|
1756
1861
|
}
|
|
1862
|
+
function memoryIdToString(id) {
|
|
1863
|
+
return String(id);
|
|
1864
|
+
}
|
|
1865
|
+
function nowUnixSeconds() {
|
|
1866
|
+
return Math.floor(Date.now() / 1e3);
|
|
1867
|
+
}
|
|
1757
1868
|
async function storeSemanticFact(transport, collection, entry) {
|
|
1758
1869
|
const response = await transport.requestJson(
|
|
1759
1870
|
"POST",
|
|
1760
1871
|
`${collectionPath(collection)}/points`,
|
|
1761
1872
|
{
|
|
1762
1873
|
points: [{
|
|
1763
|
-
id: entry.id,
|
|
1874
|
+
id: parseRestPointId(entry.id),
|
|
1764
1875
|
vector: entry.embedding,
|
|
1765
1876
|
payload: {
|
|
1766
1877
|
// Caller metadata is spread first so the reserved keys below
|
|
1767
|
-
// (`_memory_type`, `
|
|
1878
|
+
// (`_memory_type`, `content`) always win and cannot be clobbered.
|
|
1768
1879
|
...entry.metadata,
|
|
1769
1880
|
_memory_type: "semantic",
|
|
1770
|
-
|
|
1881
|
+
// `content` matches the core semantic store and the server/Python
|
|
1882
|
+
// payload field (BREAKING: was `text` before this change).
|
|
1883
|
+
content: entry.text
|
|
1771
1884
|
}
|
|
1772
1885
|
}]
|
|
1773
1886
|
}
|
|
@@ -1778,7 +1891,8 @@ async function searchSemanticMemory(transport, collection, embedding, k = 5) {
|
|
|
1778
1891
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "semantic" });
|
|
1779
1892
|
}
|
|
1780
1893
|
async function recordEpisodicEvent(transport, collection, event) {
|
|
1781
|
-
const id = generateUniqueId();
|
|
1894
|
+
const id = event.id !== void 0 ? parseRestPointId(event.id) : generateUniqueId();
|
|
1895
|
+
const timestamp = event.timestamp ?? nowUnixSeconds();
|
|
1782
1896
|
const response = await transport.requestJson(
|
|
1783
1897
|
"POST",
|
|
1784
1898
|
`${collectionPath(collection)}/points`,
|
|
@@ -1794,19 +1908,21 @@ async function recordEpisodicEvent(transport, collection, event) {
|
|
|
1794
1908
|
...event.metadata,
|
|
1795
1909
|
_memory_type: "episodic",
|
|
1796
1910
|
event_type: event.eventType,
|
|
1797
|
-
|
|
1911
|
+
// NUMERIC unix-seconds, mirroring the core episodic store so
|
|
1912
|
+
// recallRecent/recallOlderThan can range-filter on it.
|
|
1913
|
+
timestamp
|
|
1798
1914
|
}
|
|
1799
1915
|
}]
|
|
1800
1916
|
}
|
|
1801
1917
|
);
|
|
1802
1918
|
throwOnError(response);
|
|
1803
|
-
return id;
|
|
1919
|
+
return memoryIdToString(id);
|
|
1804
1920
|
}
|
|
1805
1921
|
async function recallEpisodicEvents(transport, collection, embedding, k = 5) {
|
|
1806
1922
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "episodic" });
|
|
1807
1923
|
}
|
|
1808
1924
|
async function storeProceduralPattern(transport, collection, pattern) {
|
|
1809
|
-
const id = generateUniqueId();
|
|
1925
|
+
const id = pattern.id !== void 0 ? parseRestPointId(pattern.id) : generateUniqueId();
|
|
1810
1926
|
const response = await transport.requestJson(
|
|
1811
1927
|
"POST",
|
|
1812
1928
|
`${collectionPath(collection)}/points`,
|
|
@@ -1827,11 +1943,41 @@ async function storeProceduralPattern(transport, collection, pattern) {
|
|
|
1827
1943
|
}
|
|
1828
1944
|
);
|
|
1829
1945
|
throwOnError(response);
|
|
1830
|
-
return id;
|
|
1946
|
+
return memoryIdToString(id);
|
|
1831
1947
|
}
|
|
1832
1948
|
async function matchProceduralPatterns(transport, collection, embedding, k = 5) {
|
|
1833
1949
|
return transport.searchVectors(collection, embedding, k, { _memory_type: "procedural" });
|
|
1834
1950
|
}
|
|
1951
|
+
function toEpisodicRecord(point) {
|
|
1952
|
+
const payload = point.payload ?? {};
|
|
1953
|
+
if (payload._memory_type !== "episodic") return void 0;
|
|
1954
|
+
if (typeof payload.timestamp !== "number") return void 0;
|
|
1955
|
+
return { id: String(point.id), timestamp: payload.timestamp, payload };
|
|
1956
|
+
}
|
|
1957
|
+
async function scrollEpisodicRecords(transport, collection) {
|
|
1958
|
+
const records = [];
|
|
1959
|
+
let cursor = null;
|
|
1960
|
+
do {
|
|
1961
|
+
const page = await scroll(transport, collection, {
|
|
1962
|
+
cursor: cursor ?? void 0,
|
|
1963
|
+
filter: { _memory_type: "episodic" }
|
|
1964
|
+
});
|
|
1965
|
+
for (const point of page.points) {
|
|
1966
|
+
const record = toEpisodicRecord(point);
|
|
1967
|
+
if (record !== void 0) records.push(record);
|
|
1968
|
+
}
|
|
1969
|
+
cursor = page.nextCursor;
|
|
1970
|
+
} while (cursor !== null && cursor !== void 0);
|
|
1971
|
+
return records;
|
|
1972
|
+
}
|
|
1973
|
+
async function recallRecentEvents(transport, collection, since) {
|
|
1974
|
+
const records = await scrollEpisodicRecords(transport, collection);
|
|
1975
|
+
return records.filter((r) => since === void 0 || r.timestamp >= since).sort((a, b) => b.timestamp - a.timestamp);
|
|
1976
|
+
}
|
|
1977
|
+
async function recallOlderThanEvents(transport, collection, before) {
|
|
1978
|
+
const records = await scrollEpisodicRecords(transport, collection);
|
|
1979
|
+
return records.filter((r) => r.timestamp < before).sort((a, b) => b.timestamp - a.timestamp);
|
|
1980
|
+
}
|
|
1835
1981
|
|
|
1836
1982
|
// src/search-quality.ts
|
|
1837
1983
|
function searchQualityToMode(quality) {
|
|
@@ -2064,6 +2210,64 @@ async function traverseParallel(transport, collection, request2) {
|
|
|
2064
2210
|
throwOnError(response, `Collection '${collection}'`);
|
|
2065
2211
|
return toTraverseResponse(response.data);
|
|
2066
2212
|
}
|
|
2213
|
+
async function relate(transport, collection, req) {
|
|
2214
|
+
const response = await transport.requestJson(
|
|
2215
|
+
"POST",
|
|
2216
|
+
`${collectionPath(collection)}/relations`,
|
|
2217
|
+
{
|
|
2218
|
+
source: req.source,
|
|
2219
|
+
target: req.target,
|
|
2220
|
+
rel_type: req.relType,
|
|
2221
|
+
properties: req.properties ?? {}
|
|
2222
|
+
}
|
|
2223
|
+
);
|
|
2224
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2225
|
+
return { edgeId: response.data.edge_id };
|
|
2226
|
+
}
|
|
2227
|
+
async function unrelate(transport, collection, edgeId) {
|
|
2228
|
+
const response = await transport.requestJson(
|
|
2229
|
+
"DELETE",
|
|
2230
|
+
`${collectionPath(collection)}/relations/${encodeURIComponent(String(edgeId))}`
|
|
2231
|
+
);
|
|
2232
|
+
if (response.error !== void 0) {
|
|
2233
|
+
const { code, message } = response.error;
|
|
2234
|
+
const err = parseVelesError(code, message);
|
|
2235
|
+
if (err instanceof EdgeNotFoundError) {
|
|
2236
|
+
return false;
|
|
2237
|
+
}
|
|
2238
|
+
if (code === "NOT_FOUND") {
|
|
2239
|
+
return false;
|
|
2240
|
+
}
|
|
2241
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2242
|
+
}
|
|
2243
|
+
return true;
|
|
2244
|
+
}
|
|
2245
|
+
async function getRelations(transport, collection, pointId) {
|
|
2246
|
+
const response = await transport.requestJson(
|
|
2247
|
+
"GET",
|
|
2248
|
+
`${collectionPath(collection)}/points/${encodeURIComponent(String(pointId))}/relations`
|
|
2249
|
+
);
|
|
2250
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2251
|
+
const raw = response.data;
|
|
2252
|
+
return {
|
|
2253
|
+
edges: raw.edges.map((e) => ({
|
|
2254
|
+
id: e.id,
|
|
2255
|
+
source: e.source,
|
|
2256
|
+
target: e.target,
|
|
2257
|
+
relType: e.rel_type,
|
|
2258
|
+
properties: e.properties
|
|
2259
|
+
})),
|
|
2260
|
+
count: raw.count
|
|
2261
|
+
};
|
|
2262
|
+
}
|
|
2263
|
+
async function setTtlDurable(transport, collection, pointId, ttlSeconds) {
|
|
2264
|
+
const response = await transport.requestJson(
|
|
2265
|
+
"PATCH",
|
|
2266
|
+
`${collectionPath(collection)}/points/${encodeURIComponent(String(pointId))}/ttl`,
|
|
2267
|
+
{ ttl_seconds: ttlSeconds }
|
|
2268
|
+
);
|
|
2269
|
+
throwOnError(response, `Collection '${collection}'`);
|
|
2270
|
+
}
|
|
2067
2271
|
|
|
2068
2272
|
// src/backends/query-backend.ts
|
|
2069
2273
|
function isLikelyAggregationQuery(queryString) {
|
|
@@ -2196,31 +2400,6 @@ async function collectionSanity(transport, collection) {
|
|
|
2196
2400
|
};
|
|
2197
2401
|
}
|
|
2198
2402
|
|
|
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
2403
|
// src/backends/admin-backend.ts
|
|
2225
2404
|
function mapStatsResponse(data) {
|
|
2226
2405
|
let columnStats;
|
|
@@ -2406,9 +2585,17 @@ async function streamInsert(transport, collection, docs) {
|
|
|
2406
2585
|
}
|
|
2407
2586
|
}
|
|
2408
2587
|
}
|
|
2588
|
+
function requireSafeRangeId(restId) {
|
|
2589
|
+
if (typeof restId === "string") {
|
|
2590
|
+
throw new ValidationError(
|
|
2591
|
+
`streamUpsertPoints requires ids in the JS safe integer range (0..${Number.MAX_SAFE_INTEGER}); use upsert/upsertBatch for string ids above it. Received: ${restId}`
|
|
2592
|
+
);
|
|
2593
|
+
}
|
|
2594
|
+
return restId;
|
|
2595
|
+
}
|
|
2409
2596
|
async function streamUpsertPoints(transport, collection, docs) {
|
|
2410
2597
|
const ndjsonLines = docs.map((doc) => {
|
|
2411
|
-
const restId = transport.parseRestPointId(doc.id);
|
|
2598
|
+
const restId = requireSafeRangeId(transport.parseRestPointId(doc.id));
|
|
2412
2599
|
const vector = toNumberArray(doc.vector);
|
|
2413
2600
|
const point = {
|
|
2414
2601
|
id: restId,
|
|
@@ -2599,6 +2786,22 @@ var RestBackend = class {
|
|
|
2599
2786
|
this.ensureInitialized();
|
|
2600
2787
|
return graphSearch(buildBaseTransport(this.httpConfig), c, r);
|
|
2601
2788
|
}
|
|
2789
|
+
async relate(c, req) {
|
|
2790
|
+
this.ensureInitialized();
|
|
2791
|
+
return relate(buildCrudTransport(this.httpConfig), c, req);
|
|
2792
|
+
}
|
|
2793
|
+
async unrelate(c, edgeId) {
|
|
2794
|
+
this.ensureInitialized();
|
|
2795
|
+
return unrelate(buildCrudTransport(this.httpConfig), c, edgeId);
|
|
2796
|
+
}
|
|
2797
|
+
async getRelations(c, pointId) {
|
|
2798
|
+
this.ensureInitialized();
|
|
2799
|
+
return getRelations(buildCrudTransport(this.httpConfig), c, pointId);
|
|
2800
|
+
}
|
|
2801
|
+
async setTtlDurable(c, pointId, ttlSeconds) {
|
|
2802
|
+
this.ensureInitialized();
|
|
2803
|
+
return setTtlDurable(buildCrudTransport(this.httpConfig), c, pointId, ttlSeconds);
|
|
2804
|
+
}
|
|
2602
2805
|
// Search
|
|
2603
2806
|
async search(c, q, o) {
|
|
2604
2807
|
this.ensureInitialized();
|
|
@@ -2731,6 +2934,14 @@ var RestBackend = class {
|
|
|
2731
2934
|
this.ensureInitialized();
|
|
2732
2935
|
return recallEpisodicEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, e, k);
|
|
2733
2936
|
}
|
|
2937
|
+
async recallRecentEvents(c, since) {
|
|
2938
|
+
this.ensureInitialized();
|
|
2939
|
+
return recallRecentEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, since);
|
|
2940
|
+
}
|
|
2941
|
+
async recallOlderThanEvents(c, before) {
|
|
2942
|
+
this.ensureInitialized();
|
|
2943
|
+
return recallOlderThanEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, before);
|
|
2944
|
+
}
|
|
2734
2945
|
async storeProceduralPattern(c, p) {
|
|
2735
2946
|
this.ensureInitialized();
|
|
2736
2947
|
return storeProceduralPattern(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, p);
|
|
@@ -2768,15 +2979,29 @@ var AgentMemoryClient = class {
|
|
|
2768
2979
|
async searchFacts(collection, embedding, k = 5) {
|
|
2769
2980
|
return this.backend.searchSemanticMemory(collection, embedding, k);
|
|
2770
2981
|
}
|
|
2771
|
-
/** Record an episodic event. Returns the
|
|
2982
|
+
/** Record an episodic event. Returns the point ID (string, u64-safe). */
|
|
2772
2983
|
async recordEvent(collection, event) {
|
|
2773
2984
|
return this.backend.recordEpisodicEvent(collection, event);
|
|
2774
2985
|
}
|
|
2775
|
-
/** Recall episodic events */
|
|
2986
|
+
/** Recall episodic events by vector similarity. */
|
|
2776
2987
|
async recallEvents(collection, embedding, k = 5) {
|
|
2777
2988
|
return this.backend.recallEpisodicEvents(collection, embedding, k);
|
|
2778
2989
|
}
|
|
2779
|
-
/**
|
|
2990
|
+
/**
|
|
2991
|
+
* Recall episodic events most-recent-first, optionally bounded below by
|
|
2992
|
+
* `since` (inclusive unix-seconds). Mirrors core `episodic.recent(since)`.
|
|
2993
|
+
*/
|
|
2994
|
+
async recallRecent(collection, since) {
|
|
2995
|
+
return this.backend.recallRecentEvents(collection, since);
|
|
2996
|
+
}
|
|
2997
|
+
/**
|
|
2998
|
+
* Recall episodic events strictly older than `before` (unix-seconds),
|
|
2999
|
+
* most-recent-first. Mirrors core `episodic.older_than(before)`.
|
|
3000
|
+
*/
|
|
3001
|
+
async recallOlderThan(collection, before) {
|
|
3002
|
+
return this.backend.recallOlderThanEvents(collection, before);
|
|
3003
|
+
}
|
|
3004
|
+
/** Store a procedural pattern. Returns the point ID (string, u64-safe). */
|
|
2780
3005
|
async learnProcedure(collection, pattern) {
|
|
2781
3006
|
return this.backend.storeProceduralPattern(collection, pattern);
|
|
2782
3007
|
}
|
|
@@ -2784,7 +3009,12 @@ var AgentMemoryClient = class {
|
|
|
2784
3009
|
async recallProcedures(collection, embedding, k = 5) {
|
|
2785
3010
|
return this.backend.matchProceduralPatterns(collection, embedding, k);
|
|
2786
3011
|
}
|
|
2787
|
-
/**
|
|
3012
|
+
/**
|
|
3013
|
+
* Delete a memory entry (fact, event, or procedure) by its point ID.
|
|
3014
|
+
*
|
|
3015
|
+
* Accepts the `string` ids returned by `recordEvent` / `learnProcedure`
|
|
3016
|
+
* (u64-safe decimal strings) as well as numeric ids.
|
|
3017
|
+
*/
|
|
2788
3018
|
async deleteMemory(collection, id) {
|
|
2789
3019
|
return this.backend.delete(collection, id);
|
|
2790
3020
|
}
|
|
@@ -2818,11 +3048,10 @@ function validateDocument(doc, config) {
|
|
|
2818
3048
|
validateRestPointId(doc.id, config);
|
|
2819
3049
|
}
|
|
2820
3050
|
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
|
-
);
|
|
3051
|
+
if (config.backend !== "rest") {
|
|
3052
|
+
return;
|
|
2825
3053
|
}
|
|
3054
|
+
parseRestPointId(id);
|
|
2826
3055
|
}
|
|
2827
3056
|
|
|
2828
3057
|
// src/client/search-methods.ts
|
|
@@ -3003,6 +3232,40 @@ function graphSearch2(backend, collection, request2) {
|
|
|
3003
3232
|
requireNonEmptyString(collection, "Collection");
|
|
3004
3233
|
return backend.graphSearch(collection, request2);
|
|
3005
3234
|
}
|
|
3235
|
+
function relate2(backend, collection, req) {
|
|
3236
|
+
requireNonEmptyString(collection, "Collection");
|
|
3237
|
+
if (!req.relType || typeof req.relType !== "string") {
|
|
3238
|
+
throw new ValidationError("Relation type is required and must be a string");
|
|
3239
|
+
}
|
|
3240
|
+
if (!isGraphNodeId(req.source) || !isGraphNodeId(req.target)) {
|
|
3241
|
+
throw new ValidationError("Source and target must be numbers or strings");
|
|
3242
|
+
}
|
|
3243
|
+
return backend.relate(collection, req);
|
|
3244
|
+
}
|
|
3245
|
+
function unrelate2(backend, collection, edgeId) {
|
|
3246
|
+
requireNonEmptyString(collection, "Collection");
|
|
3247
|
+
if (!isGraphNodeId(edgeId)) {
|
|
3248
|
+
throw new ValidationError("Edge ID must be a number or string");
|
|
3249
|
+
}
|
|
3250
|
+
return backend.unrelate(collection, edgeId);
|
|
3251
|
+
}
|
|
3252
|
+
function getRelations2(backend, collection, pointId) {
|
|
3253
|
+
requireNonEmptyString(collection, "Collection");
|
|
3254
|
+
if (!isGraphNodeId(pointId)) {
|
|
3255
|
+
throw new ValidationError("Point ID must be a number or string");
|
|
3256
|
+
}
|
|
3257
|
+
return backend.getRelations(collection, pointId);
|
|
3258
|
+
}
|
|
3259
|
+
function setTtlDurable2(backend, collection, pointId, ttlSeconds) {
|
|
3260
|
+
requireNonEmptyString(collection, "Collection");
|
|
3261
|
+
if (!isGraphNodeId(pointId)) {
|
|
3262
|
+
throw new ValidationError("Point ID must be a number or string");
|
|
3263
|
+
}
|
|
3264
|
+
if (typeof ttlSeconds !== "number" || ttlSeconds < 0) {
|
|
3265
|
+
throw new ValidationError("ttlSeconds must be a non-negative number");
|
|
3266
|
+
}
|
|
3267
|
+
return backend.setTtlDurable(collection, pointId, ttlSeconds);
|
|
3268
|
+
}
|
|
3006
3269
|
|
|
3007
3270
|
// src/client.ts
|
|
3008
3271
|
var VelesDB = class {
|
|
@@ -3300,6 +3563,22 @@ var VelesDB = class {
|
|
|
3300
3563
|
this.ensureInitialized();
|
|
3301
3564
|
return graphSearch2(this.backend, collection, request2);
|
|
3302
3565
|
}
|
|
3566
|
+
async relate(collection, req) {
|
|
3567
|
+
this.ensureInitialized();
|
|
3568
|
+
return relate2(this.backend, collection, req);
|
|
3569
|
+
}
|
|
3570
|
+
async unrelate(collection, edgeId) {
|
|
3571
|
+
this.ensureInitialized();
|
|
3572
|
+
return unrelate2(this.backend, collection, edgeId);
|
|
3573
|
+
}
|
|
3574
|
+
async getRelations(collection, pointId) {
|
|
3575
|
+
this.ensureInitialized();
|
|
3576
|
+
return getRelations2(this.backend, collection, pointId);
|
|
3577
|
+
}
|
|
3578
|
+
async setTtlDurable(collection, pointId, ttlSeconds) {
|
|
3579
|
+
this.ensureInitialized();
|
|
3580
|
+
return setTtlDurable2(this.backend, collection, pointId, ttlSeconds);
|
|
3581
|
+
}
|
|
3303
3582
|
// ========================================================================
|
|
3304
3583
|
// Capabilities & Backend Info
|
|
3305
3584
|
// ========================================================================
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wiscale/velesdb-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "VelesDB TypeScript SDK: The Local Vector Database for AI & RAG. Microsecond semantic search in Browser & Node.js.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"lint": "eslint src",
|
|
27
27
|
"lint:fix": "eslint src --fix",
|
|
28
28
|
"format": "prettier --write src",
|
|
29
|
-
"typecheck": "tsc --noEmit",
|
|
29
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.examples.json",
|
|
30
30
|
"prepublishOnly": "npm run build"
|
|
31
31
|
},
|
|
32
32
|
"keywords": [
|