@wiscale/velesdb-sdk 1.17.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/LICENSE +356 -20
- package/README.md +169 -11
- package/dist/index.d.mts +203 -44
- package/dist/index.d.ts +203 -44
- package/dist/index.js +391 -97
- package/dist/index.mjs +391 -97
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -2,7 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Official TypeScript SDK for [VelesDB](https://github.com/cyberlife-coder/VelesDB) -- the local-first vector database for AI and RAG. Sub-millisecond semantic search in Browser and Node.js.
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**v2.0.0** | Node.js >= 18 | Browser (WASM) | VelesDB Core License 1.0
|
|
6
|
+
|
|
7
|
+
## What's New (unreleased)
|
|
8
|
+
|
|
9
|
+
- **Relation + durable-TTL surface** (REST backend): `relate()`, `unrelate()`, `getRelations()`, `setTtlDurable()` — now fully tested and documented (see [Knowledge Graph API](#knowledge-graph-api) and [Agent Memory API](#agent-memory-api) below). The WASM backend throws `NOT_SUPPORTED` for these methods.
|
|
10
|
+
- The shipped example (`examples/hybrid_queries.ts`) was rewritten against the real API and is now compile-checked in CI.
|
|
11
|
+
|
|
12
|
+
## What's New in v2.0.0
|
|
13
|
+
|
|
14
|
+
- v2.0.0: graph dimension on agent memory — `relate()` / `relations()` / `unrelate()`; durable-TTL setters; aligns with the engine 2.0 release. See the root [CHANGELOG](../../CHANGELOG.md) for the breaking VelesQL changes.
|
|
15
|
+
- v1.18.0: agent-memory parity wave — temporal recall facades (`recallRecent` / `recallOlderThan`), id-coercion hardening for `deleteMemory(string | number)`.
|
|
6
16
|
|
|
7
17
|
## What's New in v1.16.0
|
|
8
18
|
|
|
@@ -30,7 +40,7 @@ Official TypeScript SDK for [VelesDB](https://github.com/cyberlife-coder/VelesDB
|
|
|
30
40
|
### Previous (v1.13.0)
|
|
31
41
|
|
|
32
42
|
- **WASM VelesQL executor** -- full browser-side VelesQL execution: SELECT/INSERT/UPDATE/DELETE/DDL + aggregations (COUNT/SUM/AVG/MIN/MAX) + GROUP BY/HAVING/UNION/INTERSECT/EXCEPT/JOIN/FUSION/MATCH 1-2 hops + NOT De Morgan distribution
|
|
33
|
-
- **TS SDK coverage raised
|
|
43
|
+
- **TS SDK coverage raised** -- per-file thresholds codified in `vitest.config.ts` (423 tests as of v1.13.0; the vitest suite has since grown past 770 cases). Note: the suite runs locally via `npm test` and is not currently executed in CI
|
|
34
44
|
- **SIFT1M standardized ANN benchmark** -- fvecs/ivecs loader + Criterion ef sweep on the INRIA TEXMEX dataset, feature-gated behind `--features bench-sift1m`
|
|
35
45
|
- **Security hardening** -- `validateCollectionName()` helper on TS SDK prevents VelesQL injection in `trainPq`
|
|
36
46
|
- **API consistency** -- `streamInsert` now serializes `payload: null` explicitly (matches `streamUpsertPoints`)
|
|
@@ -160,7 +170,13 @@ const queryVector = new Float32Array(1536).fill(0.1);
|
|
|
160
170
|
const results = await db.search('products', queryVector, { k: 10 });
|
|
161
171
|
```
|
|
162
172
|
|
|
163
|
-
> **REST backend note:** Document IDs must be
|
|
173
|
+
> **REST backend note:** Document IDs must be non-negative `u64` integers. Pass a JS
|
|
174
|
+
> number in the range `0..Number.MAX_SAFE_INTEGER`, or a decimal string for the full
|
|
175
|
+
> `u64` range — string ids above 2^53-1 (up to `18446744073709551615`) are kept
|
|
176
|
+
> verbatim on the wire, so the ids returned by `recordEvent`/`learnProcedure`
|
|
177
|
+
> round-trip through `get`/`delete` without precision loss. Exception: the NDJSON
|
|
178
|
+
> bulk endpoint (`streamUpsertPoints`) only accepts safe-range numeric ids.
|
|
179
|
+
> Arbitrary (non-numeric) string IDs are only supported with the WASM backend.
|
|
164
180
|
|
|
165
181
|
> **Versioned routes:** The REST backend uses `/v1/` as the canonical route prefix
|
|
166
182
|
> (e.g. `POST /v1/collections/{name}/search`). Legacy routes without the prefix
|
|
@@ -537,6 +553,14 @@ Get detailed collection configuration (dimension, metric, storage mode, point co
|
|
|
537
553
|
|
|
538
554
|
Execute a VelesQL query. Supports SELECT, WHERE, vector NEAR, GROUP BY, HAVING, ORDER BY, JOIN, UNION/INTERSECT/EXCEPT, and USING FUSION.
|
|
539
555
|
|
|
556
|
+
> **Backend support:** full VelesQL execution requires the **REST backend** (`velesdb-server`).
|
|
557
|
+
> The WASM backend only executes pure top-k vector queries of the form
|
|
558
|
+
> `SELECT * FROM <collection> WHERE vector NEAR $param [LIMIT n]` (`vector` is the
|
|
559
|
+
> grammar keyword, not a column name) and throws a
|
|
560
|
+
> `NOT_SUPPORTED` error for anything else (WHERE predicates, JOIN, GROUP BY, MATCH,
|
|
561
|
+
> set operations, FUSION) instead of silently ignoring clauses. Accordingly,
|
|
562
|
+
> `db.capabilities().velesqlQuery` is `false` on WASM.
|
|
563
|
+
|
|
540
564
|
```typescript
|
|
541
565
|
// Vector similarity search
|
|
542
566
|
const result = await db.query(
|
|
@@ -717,6 +741,56 @@ for (const node of result.results) {
|
|
|
717
741
|
}
|
|
718
742
|
```
|
|
719
743
|
|
|
744
|
+
#### `db.relate(collection, request)`
|
|
745
|
+
|
|
746
|
+
Create a typed relation edge between two existing points. Returns the
|
|
747
|
+
allocated edge ID (`RelateResponse = { edgeId: number | string }`). Point and
|
|
748
|
+
edge IDs are `number | string` — IDs above `Number.MAX_SAFE_INTEGER` travel as
|
|
749
|
+
decimal strings to avoid u64 precision loss. **REST backend only** (the WASM
|
|
750
|
+
backend throws `NOT_SUPPORTED`).
|
|
751
|
+
|
|
752
|
+
```typescript
|
|
753
|
+
const { edgeId } = await db.relate('social', {
|
|
754
|
+
source: 100,
|
|
755
|
+
target: 200,
|
|
756
|
+
relType: 'FOLLOWS',
|
|
757
|
+
properties: { since: '2024-01-01' } // optional, defaults to {}
|
|
758
|
+
});
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
#### `db.unrelate(collection, edgeId)`
|
|
762
|
+
|
|
763
|
+
Remove a relation edge by its ID. Returns `true` if the edge was removed,
|
|
764
|
+
`false` if it did not exist. **REST backend only.**
|
|
765
|
+
|
|
766
|
+
```typescript
|
|
767
|
+
const removed = await db.unrelate('social', edgeId);
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
#### `db.getRelations(collection, pointId)`
|
|
771
|
+
|
|
772
|
+
List the outgoing relation edges of a point. Returns
|
|
773
|
+
`RelationsResponse = { edges: RelationEdge[]; count: number }` where each edge
|
|
774
|
+
carries `{ id, source, target, relType, properties? }`. **REST backend only.**
|
|
775
|
+
|
|
776
|
+
```typescript
|
|
777
|
+
const { edges, count } = await db.getRelations('social', 100);
|
|
778
|
+
for (const edge of edges) {
|
|
779
|
+
console.log(`${edge.source} -[${edge.relType}]-> ${edge.target}`);
|
|
780
|
+
}
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
#### `db.setTtlDurable(collection, pointId, ttlSeconds)`
|
|
784
|
+
|
|
785
|
+
Durably set (or refresh) the time-to-live of a point, in **seconds**. The
|
|
786
|
+
expiry is persisted server-side (reserved `_veles_expires_at` payload field),
|
|
787
|
+
so it survives a restart. `ttlSeconds` must be a non-negative number.
|
|
788
|
+
**REST backend only.**
|
|
789
|
+
|
|
790
|
+
```typescript
|
|
791
|
+
await db.setTtlDurable('social', 100, 3600); // expire point 100 in 1 hour
|
|
792
|
+
```
|
|
793
|
+
|
|
720
794
|
---
|
|
721
795
|
|
|
722
796
|
### Property Indexes
|
|
@@ -772,7 +846,21 @@ const result = await db.trainPq('embeddings', {
|
|
|
772
846
|
|
|
773
847
|
### Agent Memory API
|
|
774
848
|
|
|
775
|
-
The Agent Memory API provides three memory types for AI agents, built on top of
|
|
849
|
+
The Agent Memory API provides three memory types for AI agents, built on top of
|
|
850
|
+
VelesDB's vector storage. In the TypeScript/JavaScript SDK it is accessed **over
|
|
851
|
+
REST** against a running `velesdb-server` (the Python and Rust bindings use the
|
|
852
|
+
embedded engine instead).
|
|
853
|
+
|
|
854
|
+
> **You must create the collection first.** The TS facade does **not**
|
|
855
|
+
> auto-create a collection for you. Create it with the dimension that matches
|
|
856
|
+
> your embedding model and the metric you want (`'cosine'` is the usual choice
|
|
857
|
+
> for normalized text embeddings), then call `storeFact` / `recordEvent` /
|
|
858
|
+
> `learnProcedure` against that same collection name.
|
|
859
|
+
|
|
860
|
+
> **Embeddings are caller-supplied.** There is no auto-embedding: every
|
|
861
|
+
> `embedding` you pass must come from your own embedding model (see
|
|
862
|
+
> [Embedding helper](#embedding-helper)) and its length must equal the
|
|
863
|
+
> collection dimension.
|
|
776
864
|
|
|
777
865
|
```typescript
|
|
778
866
|
import { VelesDB } from '@wiscale/velesdb-sdk';
|
|
@@ -780,13 +868,46 @@ import { VelesDB } from '@wiscale/velesdb-sdk';
|
|
|
780
868
|
const db = new VelesDB({ backend: 'rest', url: 'http://localhost:8080' });
|
|
781
869
|
await db.init();
|
|
782
870
|
|
|
871
|
+
// 1. Create the backing collection FIRST (nothing auto-creates it).
|
|
872
|
+
// The dimension must match your embedding model; cosine is typical.
|
|
873
|
+
await db.createCollection('knowledge', { dimension: 384, metric: 'cosine' });
|
|
874
|
+
|
|
875
|
+
// 2. Open the agent-memory facade.
|
|
783
876
|
const memory = db.agentMemory({ dimension: 384 });
|
|
877
|
+
|
|
878
|
+
// 3. Store and recall (embedding is your own model's output, length 384).
|
|
879
|
+
await memory.storeFact('knowledge', {
|
|
880
|
+
id: 1,
|
|
881
|
+
text: 'VelesDB uses HNSW for vector indexing',
|
|
882
|
+
embedding: factEmbedding,
|
|
883
|
+
});
|
|
884
|
+
const facts = await memory.searchFacts('knowledge', queryEmbedding, 5);
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
Each similarity-recall method (`searchFacts`, `recallEvents`,
|
|
888
|
+
`recallProcedures`) returns `SearchResult[]`:
|
|
889
|
+
|
|
890
|
+
```typescript
|
|
891
|
+
// SearchResult = { id: number; score: number; payload?: Record<string, unknown>; vector?: number[] }
|
|
784
892
|
```
|
|
785
893
|
|
|
894
|
+
The temporal-recall methods (`recallRecent`, `recallOlderThan`) return
|
|
895
|
+
`EpisodicRecord[]` instead — see [Episodic Memory](#episodic-memory-events-and-experiences).
|
|
896
|
+
|
|
897
|
+
- `score` is the cosine similarity in `[0, 1]` (for a `cosine` collection);
|
|
898
|
+
higher means more similar.
|
|
899
|
+
- `payload` carries the stored fields (`content` for semantic text,
|
|
900
|
+
`event_type` / `timestamp` for episodic, `name` / `steps` for procedural,
|
|
901
|
+
plus your metadata). The reserved payload keys `_memory_type` / `content` /
|
|
902
|
+
`event_type` / `timestamp` / `name` / `steps` always take precedence over
|
|
903
|
+
caller `metadata`/`data` of the same name, so they cannot be clobbered.
|
|
904
|
+
Note: the `SemanticEntry.text` input field is stored as `content` in the
|
|
905
|
+
payload — `result.payload?.content` is the fact text on recall.
|
|
906
|
+
|
|
786
907
|
#### Semantic Memory (facts and knowledge)
|
|
787
908
|
|
|
788
909
|
```typescript
|
|
789
|
-
// Store a fact
|
|
910
|
+
// Store a fact (id is caller-assigned; reusing an id upserts)
|
|
790
911
|
await memory.storeFact('knowledge', {
|
|
791
912
|
id: 1,
|
|
792
913
|
text: 'VelesDB uses HNSW for vector indexing',
|
|
@@ -801,25 +922,37 @@ const facts = await memory.searchFacts('knowledge', queryEmbedding, 5);
|
|
|
801
922
|
#### Episodic Memory (events and experiences)
|
|
802
923
|
|
|
803
924
|
```typescript
|
|
804
|
-
// Record an event
|
|
805
|
-
await memory.recordEvent('events', {
|
|
925
|
+
// Record an event — returns the generated point id
|
|
926
|
+
const eventId = await memory.recordEvent('events', {
|
|
806
927
|
eventType: 'user_query',
|
|
807
928
|
data: { query: 'How does HNSW work?', response: '...' },
|
|
808
929
|
embedding: eventEmbedding,
|
|
809
|
-
metadata: { timestamp: Date.now() }
|
|
810
930
|
});
|
|
811
931
|
|
|
812
932
|
// Recall similar events
|
|
813
933
|
const events = await memory.recallEvents('events', queryEmbedding, 5);
|
|
934
|
+
|
|
935
|
+
// Temporal recall — no embedding needed, most-recent-first.
|
|
936
|
+
// recallRecent(collection, since?): events with timestamp >= since
|
|
937
|
+
// (inclusive, unix-seconds); recallOlderThan(collection, before): strictly older.
|
|
938
|
+
const nowSecs = Math.floor(Date.now() / 1000);
|
|
939
|
+
const allRecent = await memory.recallRecent('events');
|
|
940
|
+
const lastHour = await memory.recallRecent('events', nowSecs - 3600);
|
|
941
|
+
const stale = await memory.recallOlderThan('events', nowSecs - 86_400);
|
|
942
|
+
|
|
943
|
+
// Both return EpisodicRecord[]:
|
|
944
|
+
// { id: string; timestamp: number; payload: Record<string, unknown> }
|
|
814
945
|
```
|
|
815
946
|
|
|
816
947
|
#### Procedural Memory (learned patterns)
|
|
817
948
|
|
|
818
949
|
```typescript
|
|
819
|
-
// Store a procedure
|
|
820
|
-
|
|
950
|
+
// Store a procedure — embedding is required so the pattern is recallable,
|
|
951
|
+
// and the generated point id is returned
|
|
952
|
+
const procId = await memory.learnProcedure('procedures', {
|
|
821
953
|
name: 'deploy-to-prod',
|
|
822
954
|
steps: ['Run tests', 'Build artifacts', 'Push to registry', 'Deploy'],
|
|
955
|
+
embedding: procedureEmbedding,
|
|
823
956
|
metadata: { lastUsed: Date.now() }
|
|
824
957
|
});
|
|
825
958
|
|
|
@@ -827,6 +960,27 @@ await memory.learnProcedure('procedures', {
|
|
|
827
960
|
const procs = await memory.recallProcedures('procedures', queryEmbedding, 3);
|
|
828
961
|
```
|
|
829
962
|
|
|
963
|
+
#### Deleting memories
|
|
964
|
+
|
|
965
|
+
```typescript
|
|
966
|
+
// Works for facts, events, and procedures — returns true if a point was removed
|
|
967
|
+
await memory.deleteMemory('procedures', procId);
|
|
968
|
+
```
|
|
969
|
+
|
|
970
|
+
> **`dimension` is advisory.** `db.agentMemory({ dimension })` records a hint you
|
|
971
|
+
> can read back via `memory.dimension`, but it does **not** create or size any
|
|
972
|
+
> collection — the collection's own dimension (set at `createCollection`)
|
|
973
|
+
> governs storage and search, and your embeddings must match it.
|
|
974
|
+
|
|
975
|
+
> **TTL & snapshots.** Durable per-point TTL (in **seconds**) **is** available
|
|
976
|
+
> from this SDK: memory entries are regular points, so
|
|
977
|
+
> [`db.setTtlDurable(collection, pointId, ttlSeconds)`](#dbsetttldurablecollection-pointid-ttlseconds)
|
|
978
|
+
> expires a fact/event/procedure durably over REST. The subsystem-namespaced
|
|
979
|
+
> TTL helpers (`set_semantic_ttl`, `store_with_ttl`, `auto_expire`) and
|
|
980
|
+
> versioned snapshots remain embedded-only (Rust **and** Python bindings) and
|
|
981
|
+
> are not exposed over REST. See the API-availability table in the
|
|
982
|
+
> [Agent Memory guide](../../docs/guides/AGENT_MEMORY.md#api-availability-by-binding).
|
|
983
|
+
|
|
830
984
|
---
|
|
831
985
|
|
|
832
986
|
## Error Handling
|
|
@@ -904,10 +1058,14 @@ import {
|
|
|
904
1058
|
type AddEdgeRequest,
|
|
905
1059
|
type TraverseRequest,
|
|
906
1060
|
type TraverseResponse,
|
|
1061
|
+
type RelateRequest,
|
|
1062
|
+
type RelateResponse,
|
|
1063
|
+
type RelationsResponse,
|
|
907
1064
|
type QueryApiResponse,
|
|
908
1065
|
type AgentMemoryConfig,
|
|
909
1066
|
type SemanticEntry,
|
|
910
1067
|
type EpisodicEvent,
|
|
1068
|
+
type EpisodicRecord,
|
|
911
1069
|
type ProceduralPattern,
|
|
912
1070
|
} from '@wiscale/velesdb-sdk';
|
|
913
1071
|
```
|
|
@@ -924,6 +1082,6 @@ import {
|
|
|
924
1082
|
|
|
925
1083
|
## License
|
|
926
1084
|
|
|
927
|
-
|
|
1085
|
+
Licensed under the [VelesDB Core License 1.0](./LICENSE) (source-available). The SDK bundles the VelesDB WASM engine and is governed by the Core License.
|
|
928
1086
|
|
|
929
1087
|
VelesDB Core and Server are licensed under VelesDB Core License 1.0 (source-available).
|