@wiscale/velesdb-sdk 2.0.0 → 3.0.1

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 CHANGED
@@ -2,10 +2,11 @@
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
- **v2.0.0** | Node.js >= 18 | Browser (WASM) | VelesDB Core License 1.0
5
+ **v3.0.1** | Node.js >= 18 | Browser (WASM) | VelesDB Core License 1.0
6
6
 
7
7
  ## What's New (unreleased)
8
8
 
9
+ - **Streaming ingestion enablement (2026-06-14)** (REST backend): `enableStreaming(collection, config?)` turns on the bounded streaming-ingestion channel before `streamInsert()`. The optional `StreamingConfig` (`bufferSize`, `batchSize`, `flushIntervalMs`) is camelCase; omitted fields fall back to the server defaults. See [`db.enableStreaming`](#dbenablestreamingcollection-config) below. The WASM backend throws `NOT_SUPPORTED`.
9
10
  - **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
11
  - The shipped example (`examples/hybrid_queries.ts`) was rewritten against the real API and is now compile-checked in CI.
11
12
 
@@ -332,6 +333,21 @@ await db.upsertBatch('docs', [
332
333
  ]);
333
334
  ```
334
335
 
336
+ #### `db.enableStreaming(collection, config?)`
337
+
338
+ Enable the bounded streaming-ingestion channel on a collection. Call this once before `streamInsert()`. The optional `config` is camelCase; every field is optional and omitted fields fall back to the server defaults (REST only; the WASM backend throws `NOT_SUPPORTED`).
339
+
340
+ | Option | Type | Default | Description |
341
+ |--------|------|---------|-------------|
342
+ | `bufferSize` | `number` | `10000` | Bounded ingestion channel capacity |
343
+ | `batchSize` | `number` | `128` | Points flushed to the index per batch |
344
+ | `flushIntervalMs` | `number` | `50` | Max milliseconds before a partial batch is flushed |
345
+
346
+ ```typescript
347
+ await db.enableStreaming('docs', { bufferSize: 4096, batchSize: 64 });
348
+ await db.streamInsert('docs', largeDocumentArray);
349
+ ```
350
+
335
351
  #### `db.streamInsert(collection, documents)`
336
352
 
337
353
  Insert documents with server backpressure support. Sends documents sequentially, respecting 429 rate limits. Throws `BackpressureError` if the server pushes back.
package/dist/index.d.mts CHANGED
@@ -1001,6 +1001,8 @@ interface CapabilityMap {
1001
1001
  secondaryIndexes: boolean;
1002
1002
  /** Agent Memory SDK (semantic, episodic, procedural). */
1003
1003
  agentMemory: boolean;
1004
+ /** Enable the bounded streaming-ingestion channel (`enableStreaming`). */
1005
+ enableStreaming: boolean;
1004
1006
  /** Streaming insert with backpressure (`streamInsert`). */
1005
1007
  streamInsert: boolean;
1006
1008
  /** Product quantization training (`trainPq`). */
@@ -1173,6 +1175,23 @@ interface AggregateResponse {
1173
1175
  count: number;
1174
1176
  };
1175
1177
  }
1178
+ /**
1179
+ * Configuration for `POST /collections/{name}/stream/enable`.
1180
+ *
1181
+ * Enables the bounded streaming-ingestion channel on a collection so that
1182
+ * subsequent `streamInsert` calls are accepted. Every field is optional;
1183
+ * omitted fields fall back to the server defaults (`bufferSize` 10000,
1184
+ * `batchSize` 128, `flushIntervalMs` 50). camelCase here, converted to the
1185
+ * snake_case wire body by the backend.
1186
+ */
1187
+ interface StreamingConfig {
1188
+ /** Bounded ingestion channel capacity (server default: 10000). */
1189
+ bufferSize?: number;
1190
+ /** Points flushed to the index per batch (server default: 128). */
1191
+ batchSize?: number;
1192
+ /** Max milliseconds before a partial batch is flushed (server default: 50). */
1193
+ flushIntervalMs?: number;
1194
+ }
1176
1195
  /**
1177
1196
  * Response from `POST /collections/{name}/points/stream` (NDJSON batch upsert).
1178
1197
  *
@@ -1220,6 +1239,17 @@ interface IVelesDBBackend {
1220
1239
  upsert(collection: string, doc: VectorDocument): Promise<void>;
1221
1240
  /** Upsert (insert or replace) multiple vectors */
1222
1241
  upsertBatch(collection: string, docs: VectorDocument[]): Promise<void>;
1242
+ /**
1243
+ * Bulk upsert multiple vectors via the binary wire format (REST only).
1244
+ *
1245
+ * Encodes `(id, vector)` pairs into the deterministic VRB1 binary layout
1246
+ * and POSTs them as `application/octet-stream`, avoiding per-point JSON
1247
+ * overhead. Payloads are not carried on this path. Not supported by the
1248
+ * WASM backend.
1249
+ *
1250
+ * @returns the number of points the server reports as inserted.
1251
+ */
1252
+ upsertBatchRaw(collection: string, docs: VectorDocument[]): Promise<number>;
1223
1253
  /** Search for similar vectors */
1224
1254
  search(collection: string, query: number[] | Float32Array, options?: SearchOptions): Promise<SearchResult[]>;
1225
1255
  /** Delete a vector by ID */
@@ -1257,6 +1287,11 @@ interface IVelesDBBackend {
1257
1287
  collectionSanity(collection: string): Promise<CollectionSanityResponse>;
1258
1288
  /** Multi-query fusion search */
1259
1289
  multiQuerySearch(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<SearchResult[]>;
1290
+ /** Multi-query fusion search returning only IDs and scores */
1291
+ multiQuerySearchIds(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<Array<{
1292
+ id: number;
1293
+ score: number;
1294
+ }>>;
1260
1295
  /** Check if collection is empty */
1261
1296
  isEmpty(collection: string): Promise<boolean>;
1262
1297
  /** Flush pending changes to disk */
@@ -1294,6 +1329,14 @@ interface IVelesDBBackend {
1294
1329
  sparseSearchNamed(collection: string, query: SparseVector, indexName: string, options?: SparseSearchNamedOptions): Promise<SearchResult[]>;
1295
1330
  /** Train Product Quantization on a collection */
1296
1331
  trainPq(collection: string, options?: PqTrainOptions): Promise<string>;
1332
+ /**
1333
+ * Enable the bounded streaming-ingestion channel on a collection.
1334
+ *
1335
+ * POSTs an optional `StreamingConfig` to
1336
+ * `POST /collections/{name}/stream/enable`; omitted config fields fall
1337
+ * back to the server defaults. Must be called before `streamInsert`.
1338
+ */
1339
+ enableStreaming(collection: string, config?: StreamingConfig): Promise<void>;
1297
1340
  /** Stream-insert documents with backpressure support */
1298
1341
  streamInsert(collection: string, docs: VectorDocument[]): Promise<void>;
1299
1342
  /**
@@ -1490,6 +1533,18 @@ declare class VelesDB {
1490
1533
  listCollections(): Promise<Collection[]>;
1491
1534
  upsert(collection: string, doc: VectorDocument): Promise<void>;
1492
1535
  upsertBatch(collection: string, docs: VectorDocument[]): Promise<void>;
1536
+ /**
1537
+ * Bulk upsert via the binary wire format (REST backend only).
1538
+ *
1539
+ * Encodes `(id, vector)` pairs into the deterministic VRB1 binary layout
1540
+ * and sends them as a single `application/octet-stream` request, avoiding
1541
+ * per-point JSON overhead. Payloads are not carried — use
1542
+ * {@link upsertBatch} when you need them. Throws a not-supported error on
1543
+ * the WASM backend.
1544
+ *
1545
+ * @returns the number of points the server reports as inserted.
1546
+ */
1547
+ upsertBatchRaw(collection: string, docs: VectorDocument[]): Promise<number>;
1493
1548
  delete(collection: string, id: string | number): Promise<boolean>;
1494
1549
  get(collection: string, id: string | number): Promise<VectorDocument | null>;
1495
1550
  isEmpty(collection: string): Promise<boolean>;
@@ -1512,6 +1567,11 @@ declare class VelesDB {
1512
1567
  filter?: FilterInput;
1513
1568
  }): Promise<SearchResult[]>;
1514
1569
  multiQuerySearch(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<SearchResult[]>;
1570
+ /** Multi-query fusion search returning only IDs and scores (no payloads). */
1571
+ multiQuerySearchIds(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<Array<{
1572
+ id: number;
1573
+ score: number;
1574
+ }>>;
1515
1575
  /**
1516
1576
  * Pure sparse search against a named sparse index.
1517
1577
  *
@@ -1526,6 +1586,7 @@ declare class VelesDB {
1526
1586
  collectionSanity(collection: string): Promise<CollectionSanityResponse>;
1527
1587
  scroll(collection: string, request?: ScrollRequest): Promise<ScrollResponse>;
1528
1588
  trainPq(collection: string, options?: PqTrainOptions): Promise<string>;
1589
+ enableStreaming(collection: string, config?: StreamingConfig): Promise<void>;
1529
1590
  streamInsert(collection: string, docs: VectorDocument[]): Promise<void>;
1530
1591
  streamUpsertPoints(collection: string, docs: VectorDocument[]): Promise<StreamUpsertResponse>;
1531
1592
  searchIds(collection: string, query: number[] | Float32Array, options?: SearchOptions): Promise<Array<{
@@ -1590,6 +1651,7 @@ declare class WasmBackend implements IVelesDBBackend {
1590
1651
  listCollections(): Promise<Collection[]>;
1591
1652
  upsert(collectionName: string, doc: VectorDocument): Promise<void>;
1592
1653
  upsertBatch(collectionName: string, docs: VectorDocument[]): Promise<void>;
1654
+ upsertBatchRaw(c: string, d: VectorDocument[]): Promise<number>;
1593
1655
  delete(collectionName: string, id: string | number): Promise<boolean>;
1594
1656
  get(collectionName: string, id: string | number): Promise<VectorDocument | null>;
1595
1657
  isEmpty(collectionName: string): Promise<boolean>;
@@ -1627,6 +1689,7 @@ declare class WasmBackend implements IVelesDBBackend {
1627
1689
  traverseParallel(c: string, r: TraverseParallelRequest): Promise<TraverseResponse>;
1628
1690
  getNodeDegree(c: string, n: number): Promise<DegreeResponse>;
1629
1691
  trainPq(c: string, o?: PqTrainOptions): Promise<string>;
1692
+ enableStreaming(c: string, cfg?: StreamingConfig): Promise<void>;
1630
1693
  streamInsert(c: string, d: VectorDocument[]): Promise<void>;
1631
1694
  streamUpsertPoints(c: string, d: VectorDocument[]): Promise<StreamUpsertResponse>;
1632
1695
  createGraphCollection(n: string, c?: GraphCollectionConfig): Promise<void>;
@@ -1637,6 +1700,10 @@ declare class WasmBackend implements IVelesDBBackend {
1637
1700
  id: number;
1638
1701
  score: number;
1639
1702
  }>>;
1703
+ multiQuerySearchIds(c: string, v: Array<number[] | Float32Array>, o?: MultiQuerySearchOptions): Promise<Array<{
1704
+ id: number;
1705
+ score: number;
1706
+ }>>;
1640
1707
  storeSemanticFact(c: string, e: SemanticEntry): Promise<void>;
1641
1708
  searchSemanticMemory(c: string, e: number[], k?: number): Promise<SearchResult[]>;
1642
1709
  recordEpisodicEvent(c: string, e: EpisodicEvent): Promise<string>;
@@ -1684,6 +1751,7 @@ declare class RestBackend implements IVelesDBBackend {
1684
1751
  listCollections(): Promise<Collection[]>;
1685
1752
  upsert(c: string, d: VectorDocument): Promise<void>;
1686
1753
  upsertBatch(c: string, d: VectorDocument[]): Promise<void>;
1754
+ upsertBatchRaw(c: string, d: VectorDocument[]): Promise<number>;
1687
1755
  delete(c: string, id: string | number): Promise<boolean>;
1688
1756
  get(c: string, id: string | number): Promise<VectorDocument | null>;
1689
1757
  isEmpty(c: string): Promise<boolean>;
@@ -1721,6 +1789,10 @@ declare class RestBackend implements IVelesDBBackend {
1721
1789
  filter?: FilterInput;
1722
1790
  }): Promise<SearchResult[]>;
1723
1791
  multiQuerySearch(c: string, v: Array<number[] | Float32Array>, o?: MultiQuerySearchOptions): Promise<SearchResult[]>;
1792
+ multiQuerySearchIds(c: string, v: Array<number[] | Float32Array>, o?: MultiQuerySearchOptions): Promise<Array<{
1793
+ id: number;
1794
+ score: number;
1795
+ }>>;
1724
1796
  searchIds(c: string, q: number[] | Float32Array, o?: SearchOptions): Promise<Array<{
1725
1797
  id: number;
1726
1798
  score: number;
@@ -1746,6 +1818,7 @@ declare class RestBackend implements IVelesDBBackend {
1746
1818
  analyzeCollection(c: string): Promise<CollectionStatsResponse>;
1747
1819
  getCollectionConfig(c: string): Promise<CollectionConfigResponse>;
1748
1820
  trainPq(c: string, o?: PqTrainOptions): Promise<string>;
1821
+ enableStreaming(c: string, cfg?: StreamingConfig): Promise<void>;
1749
1822
  streamInsert(c: string, d: VectorDocument[]): Promise<void>;
1750
1823
  streamUpsertPoints(c: string, d: VectorDocument[]): Promise<StreamUpsertResponse>;
1751
1824
  storeSemanticFact(c: string, e: SemanticEntry): Promise<void>;
@@ -2246,4 +2319,4 @@ declare class OpenAIEmbedder implements Embedder {
2246
2319
  embed(texts: string[]): Promise<number[][]>;
2247
2320
  }
2248
2321
 
2249
- export { type ActualStats, type AddEdgeRequest, AgentMemoryClient, type AgentMemoryConfig, type AggregateQueryOptions, type AggregateResponse, type AggregationQueryResponse, AllocationFailedError, type AsyncIndexBuilderOptions, type BackendType, BackpressureError, type CapabilityMap, type Collection, type CollectionConfig, type CollectionConfigResponse, CollectionExistsError, CollectionNotFoundError, type CollectionSanityChecks, type CollectionSanityDiagnostics, type CollectionSanityResponse, type CollectionStatsResponse, type CollectionType, type ColumnStatsDetail, ColumnStoreError, type CompareOp, type Condition, ConfigError, ConnectionError, type CreateIndexOptions, DatabaseLockedError, type DeferredIndexerOptions, type DegreeResponse, DimensionMismatchError, type DistanceMetric, EdgeExistsError, EdgeNotFoundError, type EdgesResponse, type Embedder, type EpisodicEvent, type EpisodicRecord, EpochMismatchError, type ExplainCost, type ExplainFeatures, type ExplainPlanStep, type ExplainResponse, type Filter, type FilterInput, type FusionOptions, type FusionStrategy, type GetEdgesOptions, type GetNodeEdgesOptions, GpuError, type GraphCollectionConfig, type GraphEdge, type GraphNodeId, GraphNotSupportedError, type GraphSchemaMode, type GraphSearchRequest, type GraphSearchResponse, type GraphSearchResultItem, GuardRailError, type GuardRailsConfigResponse, type GuardRailsUpdateRequest, type HnswParams, type IVelesDBBackend, IncompatibleSchemaVersionError, IndexCorruptedError, IndexError, type IndexInfo, type IndexType, InternalError, InvalidCollectionNameError, InvalidDimensionError, InvalidEdgeLabelError, InvalidQuantizerConfigError, InvalidVectorError, IoError, type JsonValue, type ListNodesResponse, type MatchQueryOptions, type MatchQueryResponse, type MatchQueryResultItem, type MultiQuerySearchOptions, type NearVectorOptions, NodeNotFoundError, type NodePayloadResponse, type NodeStats, NotFoundError, OpenAIEmbedder, type OpenAIEmbedderOptions, OverflowError, PointNotFoundError, type PqTrainOptions, type ProceduralPattern, type QueryApiResponse, QueryError, type QueryOptions, type QueryResponse, type QueryResult, type QueryStats, REST_CAPABILITIES, type RebuildIndexResponse, type RelDirection, type RelOptions, type RelateRequest, type RelateResponse, type RelationEdge, type RelationsResponse, RestBackend, type RestPointId, SchemaValidationError, type ScrollRequest, type ScrollResponse, SearchNotSupportedError, type SearchOptions, type SearchQuality, type SearchQualityWire, type SearchResult, type SemanticEntry, SerializationError, SnapshotBuildFailedError, SparseIndexError, type SparseSearchNamedOptions, type SparseVector, StorageError, type StorageMode, type StreamUpsertResponse, TrainingFailedError, type TraversalResultItem, type TraversalStats, type TraverseParallelRequest, type TraverseRequest, type TraverseResponse, VELES_ERROR_CODES, ValidationError, type VectorDocument, VectorNotAllowedError, VectorRequiredError, VelesDB, type VelesDBConfig, VelesDBError, VelesError, type VelesErrorCode, VelesQLBuilder, WASM_CAPABILITIES, WasmBackend, f, isTypedFilter, normalizeFilter, parseVelesError, searchQualityToMode, velesql };
2322
+ export { type ActualStats, type AddEdgeRequest, AgentMemoryClient, type AgentMemoryConfig, type AggregateQueryOptions, type AggregateResponse, type AggregationQueryResponse, AllocationFailedError, type AsyncIndexBuilderOptions, type BackendType, BackpressureError, type CapabilityMap, type Collection, type CollectionConfig, type CollectionConfigResponse, CollectionExistsError, CollectionNotFoundError, type CollectionSanityChecks, type CollectionSanityDiagnostics, type CollectionSanityResponse, type CollectionStatsResponse, type CollectionType, type ColumnStatsDetail, ColumnStoreError, type CompareOp, type Condition, ConfigError, ConnectionError, type CreateIndexOptions, DatabaseLockedError, type DeferredIndexerOptions, type DegreeResponse, DimensionMismatchError, type DistanceMetric, EdgeExistsError, EdgeNotFoundError, type EdgesResponse, type Embedder, type EpisodicEvent, type EpisodicRecord, EpochMismatchError, type ExplainCost, type ExplainFeatures, type ExplainPlanStep, type ExplainResponse, type Filter, type FilterInput, type FusionOptions, type FusionStrategy, type GetEdgesOptions, type GetNodeEdgesOptions, GpuError, type GraphCollectionConfig, type GraphEdge, type GraphNodeId, GraphNotSupportedError, type GraphSchemaMode, type GraphSearchRequest, type GraphSearchResponse, type GraphSearchResultItem, GuardRailError, type GuardRailsConfigResponse, type GuardRailsUpdateRequest, type HnswParams, type IVelesDBBackend, IncompatibleSchemaVersionError, IndexCorruptedError, IndexError, type IndexInfo, type IndexType, InternalError, InvalidCollectionNameError, InvalidDimensionError, InvalidEdgeLabelError, InvalidQuantizerConfigError, InvalidVectorError, IoError, type JsonValue, type ListNodesResponse, type MatchQueryOptions, type MatchQueryResponse, type MatchQueryResultItem, type MultiQuerySearchOptions, type NearVectorOptions, NodeNotFoundError, type NodePayloadResponse, type NodeStats, NotFoundError, OpenAIEmbedder, type OpenAIEmbedderOptions, OverflowError, PointNotFoundError, type PqTrainOptions, type ProceduralPattern, type QueryApiResponse, QueryError, type QueryOptions, type QueryResponse, type QueryResult, type QueryStats, REST_CAPABILITIES, type RebuildIndexResponse, type RelDirection, type RelOptions, type RelateRequest, type RelateResponse, type RelationEdge, type RelationsResponse, RestBackend, type RestPointId, SchemaValidationError, type ScrollRequest, type ScrollResponse, SearchNotSupportedError, type SearchOptions, type SearchQuality, type SearchQualityWire, type SearchResult, type SemanticEntry, SerializationError, SnapshotBuildFailedError, SparseIndexError, type SparseSearchNamedOptions, type SparseVector, StorageError, type StorageMode, type StreamUpsertResponse, type StreamingConfig, TrainingFailedError, type TraversalResultItem, type TraversalStats, type TraverseParallelRequest, type TraverseRequest, type TraverseResponse, VELES_ERROR_CODES, ValidationError, type VectorDocument, VectorNotAllowedError, VectorRequiredError, VelesDB, type VelesDBConfig, VelesDBError, VelesError, type VelesErrorCode, VelesQLBuilder, WASM_CAPABILITIES, WasmBackend, f, isTypedFilter, normalizeFilter, parseVelesError, searchQualityToMode, velesql };
package/dist/index.d.ts CHANGED
@@ -1001,6 +1001,8 @@ interface CapabilityMap {
1001
1001
  secondaryIndexes: boolean;
1002
1002
  /** Agent Memory SDK (semantic, episodic, procedural). */
1003
1003
  agentMemory: boolean;
1004
+ /** Enable the bounded streaming-ingestion channel (`enableStreaming`). */
1005
+ enableStreaming: boolean;
1004
1006
  /** Streaming insert with backpressure (`streamInsert`). */
1005
1007
  streamInsert: boolean;
1006
1008
  /** Product quantization training (`trainPq`). */
@@ -1173,6 +1175,23 @@ interface AggregateResponse {
1173
1175
  count: number;
1174
1176
  };
1175
1177
  }
1178
+ /**
1179
+ * Configuration for `POST /collections/{name}/stream/enable`.
1180
+ *
1181
+ * Enables the bounded streaming-ingestion channel on a collection so that
1182
+ * subsequent `streamInsert` calls are accepted. Every field is optional;
1183
+ * omitted fields fall back to the server defaults (`bufferSize` 10000,
1184
+ * `batchSize` 128, `flushIntervalMs` 50). camelCase here, converted to the
1185
+ * snake_case wire body by the backend.
1186
+ */
1187
+ interface StreamingConfig {
1188
+ /** Bounded ingestion channel capacity (server default: 10000). */
1189
+ bufferSize?: number;
1190
+ /** Points flushed to the index per batch (server default: 128). */
1191
+ batchSize?: number;
1192
+ /** Max milliseconds before a partial batch is flushed (server default: 50). */
1193
+ flushIntervalMs?: number;
1194
+ }
1176
1195
  /**
1177
1196
  * Response from `POST /collections/{name}/points/stream` (NDJSON batch upsert).
1178
1197
  *
@@ -1220,6 +1239,17 @@ interface IVelesDBBackend {
1220
1239
  upsert(collection: string, doc: VectorDocument): Promise<void>;
1221
1240
  /** Upsert (insert or replace) multiple vectors */
1222
1241
  upsertBatch(collection: string, docs: VectorDocument[]): Promise<void>;
1242
+ /**
1243
+ * Bulk upsert multiple vectors via the binary wire format (REST only).
1244
+ *
1245
+ * Encodes `(id, vector)` pairs into the deterministic VRB1 binary layout
1246
+ * and POSTs them as `application/octet-stream`, avoiding per-point JSON
1247
+ * overhead. Payloads are not carried on this path. Not supported by the
1248
+ * WASM backend.
1249
+ *
1250
+ * @returns the number of points the server reports as inserted.
1251
+ */
1252
+ upsertBatchRaw(collection: string, docs: VectorDocument[]): Promise<number>;
1223
1253
  /** Search for similar vectors */
1224
1254
  search(collection: string, query: number[] | Float32Array, options?: SearchOptions): Promise<SearchResult[]>;
1225
1255
  /** Delete a vector by ID */
@@ -1257,6 +1287,11 @@ interface IVelesDBBackend {
1257
1287
  collectionSanity(collection: string): Promise<CollectionSanityResponse>;
1258
1288
  /** Multi-query fusion search */
1259
1289
  multiQuerySearch(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<SearchResult[]>;
1290
+ /** Multi-query fusion search returning only IDs and scores */
1291
+ multiQuerySearchIds(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<Array<{
1292
+ id: number;
1293
+ score: number;
1294
+ }>>;
1260
1295
  /** Check if collection is empty */
1261
1296
  isEmpty(collection: string): Promise<boolean>;
1262
1297
  /** Flush pending changes to disk */
@@ -1294,6 +1329,14 @@ interface IVelesDBBackend {
1294
1329
  sparseSearchNamed(collection: string, query: SparseVector, indexName: string, options?: SparseSearchNamedOptions): Promise<SearchResult[]>;
1295
1330
  /** Train Product Quantization on a collection */
1296
1331
  trainPq(collection: string, options?: PqTrainOptions): Promise<string>;
1332
+ /**
1333
+ * Enable the bounded streaming-ingestion channel on a collection.
1334
+ *
1335
+ * POSTs an optional `StreamingConfig` to
1336
+ * `POST /collections/{name}/stream/enable`; omitted config fields fall
1337
+ * back to the server defaults. Must be called before `streamInsert`.
1338
+ */
1339
+ enableStreaming(collection: string, config?: StreamingConfig): Promise<void>;
1297
1340
  /** Stream-insert documents with backpressure support */
1298
1341
  streamInsert(collection: string, docs: VectorDocument[]): Promise<void>;
1299
1342
  /**
@@ -1490,6 +1533,18 @@ declare class VelesDB {
1490
1533
  listCollections(): Promise<Collection[]>;
1491
1534
  upsert(collection: string, doc: VectorDocument): Promise<void>;
1492
1535
  upsertBatch(collection: string, docs: VectorDocument[]): Promise<void>;
1536
+ /**
1537
+ * Bulk upsert via the binary wire format (REST backend only).
1538
+ *
1539
+ * Encodes `(id, vector)` pairs into the deterministic VRB1 binary layout
1540
+ * and sends them as a single `application/octet-stream` request, avoiding
1541
+ * per-point JSON overhead. Payloads are not carried — use
1542
+ * {@link upsertBatch} when you need them. Throws a not-supported error on
1543
+ * the WASM backend.
1544
+ *
1545
+ * @returns the number of points the server reports as inserted.
1546
+ */
1547
+ upsertBatchRaw(collection: string, docs: VectorDocument[]): Promise<number>;
1493
1548
  delete(collection: string, id: string | number): Promise<boolean>;
1494
1549
  get(collection: string, id: string | number): Promise<VectorDocument | null>;
1495
1550
  isEmpty(collection: string): Promise<boolean>;
@@ -1512,6 +1567,11 @@ declare class VelesDB {
1512
1567
  filter?: FilterInput;
1513
1568
  }): Promise<SearchResult[]>;
1514
1569
  multiQuerySearch(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<SearchResult[]>;
1570
+ /** Multi-query fusion search returning only IDs and scores (no payloads). */
1571
+ multiQuerySearchIds(collection: string, vectors: Array<number[] | Float32Array>, options?: MultiQuerySearchOptions): Promise<Array<{
1572
+ id: number;
1573
+ score: number;
1574
+ }>>;
1515
1575
  /**
1516
1576
  * Pure sparse search against a named sparse index.
1517
1577
  *
@@ -1526,6 +1586,7 @@ declare class VelesDB {
1526
1586
  collectionSanity(collection: string): Promise<CollectionSanityResponse>;
1527
1587
  scroll(collection: string, request?: ScrollRequest): Promise<ScrollResponse>;
1528
1588
  trainPq(collection: string, options?: PqTrainOptions): Promise<string>;
1589
+ enableStreaming(collection: string, config?: StreamingConfig): Promise<void>;
1529
1590
  streamInsert(collection: string, docs: VectorDocument[]): Promise<void>;
1530
1591
  streamUpsertPoints(collection: string, docs: VectorDocument[]): Promise<StreamUpsertResponse>;
1531
1592
  searchIds(collection: string, query: number[] | Float32Array, options?: SearchOptions): Promise<Array<{
@@ -1590,6 +1651,7 @@ declare class WasmBackend implements IVelesDBBackend {
1590
1651
  listCollections(): Promise<Collection[]>;
1591
1652
  upsert(collectionName: string, doc: VectorDocument): Promise<void>;
1592
1653
  upsertBatch(collectionName: string, docs: VectorDocument[]): Promise<void>;
1654
+ upsertBatchRaw(c: string, d: VectorDocument[]): Promise<number>;
1593
1655
  delete(collectionName: string, id: string | number): Promise<boolean>;
1594
1656
  get(collectionName: string, id: string | number): Promise<VectorDocument | null>;
1595
1657
  isEmpty(collectionName: string): Promise<boolean>;
@@ -1627,6 +1689,7 @@ declare class WasmBackend implements IVelesDBBackend {
1627
1689
  traverseParallel(c: string, r: TraverseParallelRequest): Promise<TraverseResponse>;
1628
1690
  getNodeDegree(c: string, n: number): Promise<DegreeResponse>;
1629
1691
  trainPq(c: string, o?: PqTrainOptions): Promise<string>;
1692
+ enableStreaming(c: string, cfg?: StreamingConfig): Promise<void>;
1630
1693
  streamInsert(c: string, d: VectorDocument[]): Promise<void>;
1631
1694
  streamUpsertPoints(c: string, d: VectorDocument[]): Promise<StreamUpsertResponse>;
1632
1695
  createGraphCollection(n: string, c?: GraphCollectionConfig): Promise<void>;
@@ -1637,6 +1700,10 @@ declare class WasmBackend implements IVelesDBBackend {
1637
1700
  id: number;
1638
1701
  score: number;
1639
1702
  }>>;
1703
+ multiQuerySearchIds(c: string, v: Array<number[] | Float32Array>, o?: MultiQuerySearchOptions): Promise<Array<{
1704
+ id: number;
1705
+ score: number;
1706
+ }>>;
1640
1707
  storeSemanticFact(c: string, e: SemanticEntry): Promise<void>;
1641
1708
  searchSemanticMemory(c: string, e: number[], k?: number): Promise<SearchResult[]>;
1642
1709
  recordEpisodicEvent(c: string, e: EpisodicEvent): Promise<string>;
@@ -1684,6 +1751,7 @@ declare class RestBackend implements IVelesDBBackend {
1684
1751
  listCollections(): Promise<Collection[]>;
1685
1752
  upsert(c: string, d: VectorDocument): Promise<void>;
1686
1753
  upsertBatch(c: string, d: VectorDocument[]): Promise<void>;
1754
+ upsertBatchRaw(c: string, d: VectorDocument[]): Promise<number>;
1687
1755
  delete(c: string, id: string | number): Promise<boolean>;
1688
1756
  get(c: string, id: string | number): Promise<VectorDocument | null>;
1689
1757
  isEmpty(c: string): Promise<boolean>;
@@ -1721,6 +1789,10 @@ declare class RestBackend implements IVelesDBBackend {
1721
1789
  filter?: FilterInput;
1722
1790
  }): Promise<SearchResult[]>;
1723
1791
  multiQuerySearch(c: string, v: Array<number[] | Float32Array>, o?: MultiQuerySearchOptions): Promise<SearchResult[]>;
1792
+ multiQuerySearchIds(c: string, v: Array<number[] | Float32Array>, o?: MultiQuerySearchOptions): Promise<Array<{
1793
+ id: number;
1794
+ score: number;
1795
+ }>>;
1724
1796
  searchIds(c: string, q: number[] | Float32Array, o?: SearchOptions): Promise<Array<{
1725
1797
  id: number;
1726
1798
  score: number;
@@ -1746,6 +1818,7 @@ declare class RestBackend implements IVelesDBBackend {
1746
1818
  analyzeCollection(c: string): Promise<CollectionStatsResponse>;
1747
1819
  getCollectionConfig(c: string): Promise<CollectionConfigResponse>;
1748
1820
  trainPq(c: string, o?: PqTrainOptions): Promise<string>;
1821
+ enableStreaming(c: string, cfg?: StreamingConfig): Promise<void>;
1749
1822
  streamInsert(c: string, d: VectorDocument[]): Promise<void>;
1750
1823
  streamUpsertPoints(c: string, d: VectorDocument[]): Promise<StreamUpsertResponse>;
1751
1824
  storeSemanticFact(c: string, e: SemanticEntry): Promise<void>;
@@ -2246,4 +2319,4 @@ declare class OpenAIEmbedder implements Embedder {
2246
2319
  embed(texts: string[]): Promise<number[][]>;
2247
2320
  }
2248
2321
 
2249
- export { type ActualStats, type AddEdgeRequest, AgentMemoryClient, type AgentMemoryConfig, type AggregateQueryOptions, type AggregateResponse, type AggregationQueryResponse, AllocationFailedError, type AsyncIndexBuilderOptions, type BackendType, BackpressureError, type CapabilityMap, type Collection, type CollectionConfig, type CollectionConfigResponse, CollectionExistsError, CollectionNotFoundError, type CollectionSanityChecks, type CollectionSanityDiagnostics, type CollectionSanityResponse, type CollectionStatsResponse, type CollectionType, type ColumnStatsDetail, ColumnStoreError, type CompareOp, type Condition, ConfigError, ConnectionError, type CreateIndexOptions, DatabaseLockedError, type DeferredIndexerOptions, type DegreeResponse, DimensionMismatchError, type DistanceMetric, EdgeExistsError, EdgeNotFoundError, type EdgesResponse, type Embedder, type EpisodicEvent, type EpisodicRecord, EpochMismatchError, type ExplainCost, type ExplainFeatures, type ExplainPlanStep, type ExplainResponse, type Filter, type FilterInput, type FusionOptions, type FusionStrategy, type GetEdgesOptions, type GetNodeEdgesOptions, GpuError, type GraphCollectionConfig, type GraphEdge, type GraphNodeId, GraphNotSupportedError, type GraphSchemaMode, type GraphSearchRequest, type GraphSearchResponse, type GraphSearchResultItem, GuardRailError, type GuardRailsConfigResponse, type GuardRailsUpdateRequest, type HnswParams, type IVelesDBBackend, IncompatibleSchemaVersionError, IndexCorruptedError, IndexError, type IndexInfo, type IndexType, InternalError, InvalidCollectionNameError, InvalidDimensionError, InvalidEdgeLabelError, InvalidQuantizerConfigError, InvalidVectorError, IoError, type JsonValue, type ListNodesResponse, type MatchQueryOptions, type MatchQueryResponse, type MatchQueryResultItem, type MultiQuerySearchOptions, type NearVectorOptions, NodeNotFoundError, type NodePayloadResponse, type NodeStats, NotFoundError, OpenAIEmbedder, type OpenAIEmbedderOptions, OverflowError, PointNotFoundError, type PqTrainOptions, type ProceduralPattern, type QueryApiResponse, QueryError, type QueryOptions, type QueryResponse, type QueryResult, type QueryStats, REST_CAPABILITIES, type RebuildIndexResponse, type RelDirection, type RelOptions, type RelateRequest, type RelateResponse, type RelationEdge, type RelationsResponse, RestBackend, type RestPointId, SchemaValidationError, type ScrollRequest, type ScrollResponse, SearchNotSupportedError, type SearchOptions, type SearchQuality, type SearchQualityWire, type SearchResult, type SemanticEntry, SerializationError, SnapshotBuildFailedError, SparseIndexError, type SparseSearchNamedOptions, type SparseVector, StorageError, type StorageMode, type StreamUpsertResponse, TrainingFailedError, type TraversalResultItem, type TraversalStats, type TraverseParallelRequest, type TraverseRequest, type TraverseResponse, VELES_ERROR_CODES, ValidationError, type VectorDocument, VectorNotAllowedError, VectorRequiredError, VelesDB, type VelesDBConfig, VelesDBError, VelesError, type VelesErrorCode, VelesQLBuilder, WASM_CAPABILITIES, WasmBackend, f, isTypedFilter, normalizeFilter, parseVelesError, searchQualityToMode, velesql };
2322
+ export { type ActualStats, type AddEdgeRequest, AgentMemoryClient, type AgentMemoryConfig, type AggregateQueryOptions, type AggregateResponse, type AggregationQueryResponse, AllocationFailedError, type AsyncIndexBuilderOptions, type BackendType, BackpressureError, type CapabilityMap, type Collection, type CollectionConfig, type CollectionConfigResponse, CollectionExistsError, CollectionNotFoundError, type CollectionSanityChecks, type CollectionSanityDiagnostics, type CollectionSanityResponse, type CollectionStatsResponse, type CollectionType, type ColumnStatsDetail, ColumnStoreError, type CompareOp, type Condition, ConfigError, ConnectionError, type CreateIndexOptions, DatabaseLockedError, type DeferredIndexerOptions, type DegreeResponse, DimensionMismatchError, type DistanceMetric, EdgeExistsError, EdgeNotFoundError, type EdgesResponse, type Embedder, type EpisodicEvent, type EpisodicRecord, EpochMismatchError, type ExplainCost, type ExplainFeatures, type ExplainPlanStep, type ExplainResponse, type Filter, type FilterInput, type FusionOptions, type FusionStrategy, type GetEdgesOptions, type GetNodeEdgesOptions, GpuError, type GraphCollectionConfig, type GraphEdge, type GraphNodeId, GraphNotSupportedError, type GraphSchemaMode, type GraphSearchRequest, type GraphSearchResponse, type GraphSearchResultItem, GuardRailError, type GuardRailsConfigResponse, type GuardRailsUpdateRequest, type HnswParams, type IVelesDBBackend, IncompatibleSchemaVersionError, IndexCorruptedError, IndexError, type IndexInfo, type IndexType, InternalError, InvalidCollectionNameError, InvalidDimensionError, InvalidEdgeLabelError, InvalidQuantizerConfigError, InvalidVectorError, IoError, type JsonValue, type ListNodesResponse, type MatchQueryOptions, type MatchQueryResponse, type MatchQueryResultItem, type MultiQuerySearchOptions, type NearVectorOptions, NodeNotFoundError, type NodePayloadResponse, type NodeStats, NotFoundError, OpenAIEmbedder, type OpenAIEmbedderOptions, OverflowError, PointNotFoundError, type PqTrainOptions, type ProceduralPattern, type QueryApiResponse, QueryError, type QueryOptions, type QueryResponse, type QueryResult, type QueryStats, REST_CAPABILITIES, type RebuildIndexResponse, type RelDirection, type RelOptions, type RelateRequest, type RelateResponse, type RelationEdge, type RelationsResponse, RestBackend, type RestPointId, SchemaValidationError, type ScrollRequest, type ScrollResponse, SearchNotSupportedError, type SearchOptions, type SearchQuality, type SearchQualityWire, type SearchResult, type SemanticEntry, SerializationError, SnapshotBuildFailedError, SparseIndexError, type SparseSearchNamedOptions, type SparseVector, StorageError, type StorageMode, type StreamUpsertResponse, type StreamingConfig, TrainingFailedError, type TraversalResultItem, type TraversalStats, type TraverseParallelRequest, type TraverseRequest, type TraverseResponse, VELES_ERROR_CODES, ValidationError, type VectorDocument, VectorNotAllowedError, VectorRequiredError, VelesDB, type VelesDBConfig, VelesDBError, VelesError, type VelesErrorCode, VelesQLBuilder, WASM_CAPABILITIES, WasmBackend, f, isTypedFilter, normalizeFilter, parseVelesError, searchQualityToMode, velesql };
package/dist/index.js CHANGED
@@ -5,8 +5,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __esm = (fn, res) => function __init() {
9
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ var __esm = (fn, res, err) => function __init() {
9
+ if (err) throw err[0];
10
+ try {
11
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ } catch (e) {
13
+ throw err = [e], e;
14
+ }
10
15
  };
11
16
  var __export = (target, all) => {
12
17
  for (var name in all)
@@ -182,6 +187,7 @@ var REST_CAPABILITIES = Object.freeze({
182
187
  graphTraversal: true,
183
188
  secondaryIndexes: true,
184
189
  agentMemory: true,
190
+ enableStreaming: true,
185
191
  streamInsert: true,
186
192
  pqTraining: true,
187
193
  velesqlQuery: true,
@@ -197,6 +203,7 @@ var WASM_CAPABILITIES = Object.freeze({
197
203
  graphTraversal: false,
198
204
  secondaryIndexes: false,
199
205
  agentMemory: false,
206
+ enableStreaming: false,
200
207
  streamInsert: false,
201
208
  pqTraining: false,
202
209
  velesqlQuery: false,
@@ -891,6 +898,9 @@ function validateCollectionName(name) {
891
898
  );
892
899
  }
893
900
  }
901
+ async function safeJsonParse(response) {
902
+ return response.json().catch(() => ({}));
903
+ }
894
904
  function toNumberArray(v) {
895
905
  return v instanceof Float32Array ? Array.from(v) : v;
896
906
  }
@@ -944,12 +954,18 @@ async function wasmScroll(_collection, _request) {
944
954
  async function wasmTrainPq(_collection, _options) {
945
955
  wasmNotSupported("PQ training");
946
956
  }
957
+ async function wasmEnableStreaming(_collection, _config) {
958
+ wasmNotSupported("Streaming enable");
959
+ }
947
960
  async function wasmStreamInsert(_collection, _docs) {
948
961
  wasmNotSupported("Streaming insert");
949
962
  }
950
963
  async function wasmStreamUpsertPoints(_collection, _docs) {
951
964
  wasmNotSupported("Streaming batch upsert");
952
965
  }
966
+ async function wasmUpsertBatchRaw(_collection, _docs) {
967
+ wasmNotSupported("Binary bulk upsert (upsertBatchRaw)");
968
+ }
953
969
  async function wasmCreateGraphCollection(_name, _config) {
954
970
  wasmNotSupported("Graph collections");
955
971
  }
@@ -965,6 +981,9 @@ async function wasmGetCollectionConfig(_collection) {
965
981
  async function wasmSearchIds(_collection, _query, _options) {
966
982
  wasmNotSupported("searchIds");
967
983
  }
984
+ async function wasmMultiQuerySearchIds(_collection, _vectors, _options) {
985
+ wasmNotSupported("multiQuerySearchIds");
986
+ }
968
987
  async function wasmStoreSemanticFact(_collection, _entry) {
969
988
  wasmNotSupported("Agent memory");
970
989
  }
@@ -1221,6 +1240,9 @@ var WasmBackend = class {
1221
1240
  }
1222
1241
  }
1223
1242
  }
1243
+ async upsertBatchRaw(c, d) {
1244
+ return wasmUpsertBatchRaw(c, d);
1245
+ }
1224
1246
  async delete(collectionName, id) {
1225
1247
  this.ensureInitialized();
1226
1248
  const collection = this.collections.get(collectionName);
@@ -1352,6 +1374,10 @@ var WasmBackend = class {
1352
1374
  this.ensureInitialized();
1353
1375
  return wasmTrainPq(c, o);
1354
1376
  }
1377
+ async enableStreaming(c, cfg) {
1378
+ this.ensureInitialized();
1379
+ return wasmEnableStreaming(c, cfg);
1380
+ }
1355
1381
  async streamInsert(c, d) {
1356
1382
  this.ensureInitialized();
1357
1383
  return wasmStreamInsert(c, d);
@@ -1380,6 +1406,10 @@ var WasmBackend = class {
1380
1406
  this.ensureInitialized();
1381
1407
  return wasmSearchIds(c, q, o);
1382
1408
  }
1409
+ async multiQuerySearchIds(c, v, o) {
1410
+ this.ensureInitialized();
1411
+ return wasmMultiQuerySearchIds(c, v, o);
1412
+ }
1383
1413
  async storeSemanticFact(c, e) {
1384
1414
  this.ensureInitialized();
1385
1415
  return wasmStoreSemanticFact(c, e);
@@ -1484,6 +1514,9 @@ var WasmBackend = class {
1484
1514
  };
1485
1515
 
1486
1516
  // src/backends/crud-backend.ts
1517
+ var RAW_BULK_HEADER_LEN = 16;
1518
+ var RAW_BULK_MAGIC = [86, 82, 66, 49];
1519
+ var RAW_BULK_ID_WIDTH = 8;
1487
1520
  var U64_MAX = 18446744073709551615n;
1488
1521
  function coerceDecimalStringId(id) {
1489
1522
  if (!/^\d+$/.test(id)) return NaN;
@@ -1634,6 +1667,105 @@ async function flush(transport, collection) {
1634
1667
  );
1635
1668
  throwOnError(response, `Collection '${collection}'`);
1636
1669
  }
1670
+ function encodeRawBulk(ids, vectors, dim) {
1671
+ const count = ids.length;
1672
+ if (vectors.length !== count) {
1673
+ throw new ValidationError(
1674
+ `encodeRawBulk: ids length (${count}) must match vectors length (${vectors.length})`
1675
+ );
1676
+ }
1677
+ const buf = new Uint8Array(RAW_BULK_HEADER_LEN + count * 8 + count * dim * 4);
1678
+ const view = new DataView(buf.buffer);
1679
+ buf.set(RAW_BULK_MAGIC, 0);
1680
+ view.setUint32(4, count, true);
1681
+ view.setUint32(8, dim, true);
1682
+ buf[12] = RAW_BULK_ID_WIDTH;
1683
+ writeIds(view, ids);
1684
+ writeVectors(view, vectors, dim, count);
1685
+ return buf;
1686
+ }
1687
+ function writeIds(view, ids) {
1688
+ let off = RAW_BULK_HEADER_LEN;
1689
+ for (const id of ids) {
1690
+ view.setBigUint64(off, BigInt(id), true);
1691
+ off += 8;
1692
+ }
1693
+ }
1694
+ function writeVectors(view, vectors, dim, count) {
1695
+ let off = RAW_BULK_HEADER_LEN + count * 8;
1696
+ for (const vec of vectors) {
1697
+ if (vec.length !== dim) {
1698
+ throw new ValidationError(
1699
+ `encodeRawBulk: vector length (${vec.length}) must match dim (${dim})`
1700
+ );
1701
+ }
1702
+ for (let i = 0; i < dim; i++) {
1703
+ view.setFloat32(off, vec[i] ?? 0, true);
1704
+ off += 4;
1705
+ }
1706
+ }
1707
+ }
1708
+ async function upsertBatchRaw(transport, collection, docs, dim) {
1709
+ const ids = docs.map((d) => coerceNumericId(d.id));
1710
+ const vectors = docs.map((d) => d.vector);
1711
+ const body = encodeRawBulk(ids, vectors, dim);
1712
+ return sendRawBulk(transport, collection, body);
1713
+ }
1714
+ function coerceNumericId(id) {
1715
+ const parsed = parseRestPointId(id);
1716
+ if (typeof parsed === "string") {
1717
+ throw new ValidationError(
1718
+ `upsertBatchRaw requires ids in the JS safe integer range; received: ${parsed}`
1719
+ );
1720
+ }
1721
+ return parsed;
1722
+ }
1723
+ async function sendRawBulk(transport, collection, body) {
1724
+ const url = `${transport.baseUrl}${collectionPath(collection)}/points/raw`;
1725
+ const headers = {
1726
+ "Content-Type": "application/octet-stream"
1727
+ };
1728
+ if (transport.apiKey) {
1729
+ headers["Authorization"] = `Bearer ${transport.apiKey}`;
1730
+ }
1731
+ const controller = new AbortController();
1732
+ const timeoutId = setTimeout(() => controller.abort(), transport.timeout);
1733
+ try {
1734
+ const response = await fetch(url, {
1735
+ method: "POST",
1736
+ headers,
1737
+ body,
1738
+ signal: controller.signal
1739
+ });
1740
+ clearTimeout(timeoutId);
1741
+ return await parseRawBulkResponse(response);
1742
+ } catch (error) {
1743
+ clearTimeout(timeoutId);
1744
+ throw wrapRawBulkError(error);
1745
+ }
1746
+ }
1747
+ async function parseRawBulkResponse(response) {
1748
+ const data = await safeJsonParse(response);
1749
+ if (!response.ok) {
1750
+ const code = typeof data.code === "string" ? data.code : `HTTP_${response.status}`;
1751
+ const message = typeof data.error === "string" ? data.error : `HTTP ${response.status}`;
1752
+ throw new VelesDBError(message, code);
1753
+ }
1754
+ return typeof data.count === "number" ? data.count : 0;
1755
+ }
1756
+ function wrapRawBulkError(error) {
1757
+ if (error instanceof VelesDBError) {
1758
+ return error;
1759
+ }
1760
+ if (error instanceof Error && error.name === "AbortError") {
1761
+ return new ConnectionError("Request timeout");
1762
+ }
1763
+ const message = error instanceof Error ? error.message : "Unknown error";
1764
+ return new ConnectionError(
1765
+ `Raw bulk upsert failed: ${message}`,
1766
+ error instanceof Error ? error : void 0
1767
+ );
1768
+ }
1637
1769
 
1638
1770
  // src/backends/rest-http.ts
1639
1771
  var STATUS_ERROR_CODES = {
@@ -1704,7 +1836,7 @@ async function request(config, method, path, body) {
1704
1836
  signal: controller.signal
1705
1837
  });
1706
1838
  clearTimeout(timeoutId);
1707
- const data = await response.json().catch(() => ({}));
1839
+ const data = await safeJsonParse(response);
1708
1840
  if (!response.ok) {
1709
1841
  const ep = extractErrorPayload(data);
1710
1842
  return { error: {
@@ -1728,6 +1860,13 @@ function buildCrudTransport(config) {
1728
1860
  requestJson: (m, p, b) => request(config, m, p, b)
1729
1861
  };
1730
1862
  }
1863
+ function buildRawBulkTransport(config) {
1864
+ return {
1865
+ baseUrl: config.baseUrl,
1866
+ apiKey: config.apiKey,
1867
+ timeout: config.timeout
1868
+ };
1869
+ }
1731
1870
  function buildSearchTransport(config) {
1732
1871
  return {
1733
1872
  requestJson: (m, p, b) => request(config, m, p, b),
@@ -2215,6 +2354,22 @@ async function multiQuerySearch(transport, collection, vectors, options) {
2215
2354
  throwOnError(response, `Collection '${collection}'`);
2216
2355
  return response.data?.results ?? [];
2217
2356
  }
2357
+ async function multiQuerySearchIds(transport, collection, vectors, options) {
2358
+ const formattedVectors = vectors.map(toNumberArray);
2359
+ const response = await transport.requestJson("POST", `${collectionPath(collection)}/search/multi/ids`, {
2360
+ vectors: formattedVectors,
2361
+ top_k: options?.k ?? 10,
2362
+ strategy: options?.fusion ?? "rrf",
2363
+ rrf_k: options?.fusionParams?.k ?? 60,
2364
+ avg_weight: options?.fusionParams?.avgWeight,
2365
+ max_weight: options?.fusionParams?.maxWeight,
2366
+ hit_weight: options?.fusionParams?.hitWeight,
2367
+ dense_weight: options?.fusionParams?.denseWeight,
2368
+ sparse_weight: options?.fusionParams?.sparseWeight
2369
+ });
2370
+ throwOnError(response, `Collection '${collection}'`);
2371
+ return response.data?.results ?? [];
2372
+ }
2218
2373
  async function sparseSearchNamed(transport, collection, query3, indexName, options) {
2219
2374
  const body = {
2220
2375
  sparse_vectors: { [indexName]: transport.sparseToRest(query3) },
@@ -2432,7 +2587,7 @@ async function query(transport, collection, queryString, params, options) {
2432
2587
  );
2433
2588
  throwOnError(response, `Collection '${collection}'`);
2434
2589
  const rawData = response.data;
2435
- if (rawData && Object.prototype.hasOwnProperty.call(rawData, "result")) {
2590
+ if (rawData != null && Object.prototype.hasOwnProperty.call(rawData, "result")) {
2436
2591
  return {
2437
2592
  result: rawData.result,
2438
2593
  stats: {
@@ -2702,7 +2857,7 @@ async function streamInsert(transport, collection, docs) {
2702
2857
  throw new BackpressureError();
2703
2858
  }
2704
2859
  if (!response.ok && response.status !== 202) {
2705
- const data = await response.json().catch(() => ({}));
2860
+ const data = await safeJsonParse(response);
2706
2861
  const errorPayload = transport.extractErrorPayload(data);
2707
2862
  throw new VelesDBError(
2708
2863
  errorPayload.message ?? `HTTP ${response.status}`,
@@ -2724,6 +2879,24 @@ async function streamInsert(transport, collection, docs) {
2724
2879
  }
2725
2880
  }
2726
2881
  }
2882
+ async function enableStreaming(transport, collection, config) {
2883
+ const body = {};
2884
+ if (config?.bufferSize !== void 0) {
2885
+ body.buffer_size = config.bufferSize;
2886
+ }
2887
+ if (config?.batchSize !== void 0) {
2888
+ body.batch_size = config.batchSize;
2889
+ }
2890
+ if (config?.flushIntervalMs !== void 0) {
2891
+ body.flush_interval_ms = config.flushIntervalMs;
2892
+ }
2893
+ const response = await transport.requestJson(
2894
+ "POST",
2895
+ `${collectionPath(collection)}/stream/enable`,
2896
+ body
2897
+ );
2898
+ throwOnError(response);
2899
+ }
2727
2900
  function requireSafeRangeId(restId) {
2728
2901
  if (typeof restId === "string") {
2729
2902
  throw new ValidationError(
@@ -2768,14 +2941,14 @@ async function streamUpsertPoints(transport, collection, docs) {
2768
2941
  throw new BackpressureError();
2769
2942
  }
2770
2943
  if (!response.ok) {
2771
- const data2 = await response.json().catch(() => ({}));
2944
+ const data2 = await safeJsonParse(response);
2772
2945
  const errorPayload = transport.extractErrorPayload(data2);
2773
2946
  throw new VelesDBError(
2774
2947
  errorPayload.message ?? `HTTP ${response.status}`,
2775
2948
  errorPayload.code ?? transport.mapStatusToErrorCode(response.status)
2776
2949
  );
2777
2950
  }
2778
- const data = await response.json().catch(() => ({}));
2951
+ const data = await safeJsonParse(response);
2779
2952
  return {
2780
2953
  message: typeof data.message === "string" ? data.message : "Stream processed",
2781
2954
  inserted: typeof data.inserted === "number" ? data.inserted : 0,
@@ -2860,6 +3033,10 @@ var RestBackend = class {
2860
3033
  this.ensureInitialized();
2861
3034
  return upsertBatch(buildCrudTransport(this.httpConfig), c, d);
2862
3035
  }
3036
+ async upsertBatchRaw(c, d) {
3037
+ this.ensureInitialized();
3038
+ return upsertBatchRaw(buildRawBulkTransport(this.httpConfig), c, d, d[0]?.vector.length ?? 0);
3039
+ }
2863
3040
  async delete(c, id) {
2864
3041
  this.ensureInitialized();
2865
3042
  return deletePoint(buildCrudTransport(this.httpConfig), c, id);
@@ -2962,6 +3139,10 @@ var RestBackend = class {
2962
3139
  this.ensureInitialized();
2963
3140
  return multiQuerySearch(buildSearchTransport(this.httpConfig), c, v, o);
2964
3141
  }
3142
+ async multiQuerySearchIds(c, v, o) {
3143
+ this.ensureInitialized();
3144
+ return multiQuerySearchIds(buildSearchTransport(this.httpConfig), c, v, o);
3145
+ }
2965
3146
  async searchIds(c, q, o) {
2966
3147
  this.ensureInitialized();
2967
3148
  return searchIds(buildSearchTransport(this.httpConfig), c, q, o);
@@ -3048,6 +3229,10 @@ var RestBackend = class {
3048
3229
  this.ensureInitialized();
3049
3230
  return trainPq(buildStreamingTransport(this.httpConfig), c, o);
3050
3231
  }
3232
+ async enableStreaming(c, cfg) {
3233
+ this.ensureInitialized();
3234
+ return enableStreaming(buildStreamingTransport(this.httpConfig), c, cfg);
3235
+ }
3051
3236
  async streamInsert(c, d) {
3052
3237
  this.ensureInitialized();
3053
3238
  return streamInsert(buildStreamingTransport(this.httpConfig), c, d);
@@ -3230,9 +3415,21 @@ function multiQuerySearch2(backend, collection, vectors, options) {
3230
3415
  }
3231
3416
  return backend.multiQuerySearch(collection, vectors, options);
3232
3417
  }
3418
+ function multiQuerySearchIds2(backend, collection, vectors, options) {
3419
+ if (!Array.isArray(vectors) || vectors.length === 0) {
3420
+ throw new ValidationError("Vectors must be a non-empty array");
3421
+ }
3422
+ for (const v of vectors) {
3423
+ requireVector(v, "Each vector");
3424
+ }
3425
+ return backend.multiQuerySearchIds(collection, vectors, options);
3426
+ }
3233
3427
  function trainPq2(backend, collection, options) {
3234
3428
  return backend.trainPq(collection, options);
3235
3429
  }
3430
+ function enableStreaming2(backend, collection, config) {
3431
+ return backend.enableStreaming(collection, config);
3432
+ }
3236
3433
  function streamInsert2(backend, config, collection, docs) {
3237
3434
  validateDocsBatch(docs, (doc) => {
3238
3435
  validateDocument(doc, config);
@@ -3501,6 +3698,24 @@ var VelesDB = class {
3501
3698
  });
3502
3699
  await this.backend.upsertBatch(collection, docs);
3503
3700
  }
3701
+ /**
3702
+ * Bulk upsert via the binary wire format (REST backend only).
3703
+ *
3704
+ * Encodes `(id, vector)` pairs into the deterministic VRB1 binary layout
3705
+ * and sends them as a single `application/octet-stream` request, avoiding
3706
+ * per-point JSON overhead. Payloads are not carried — use
3707
+ * {@link upsertBatch} when you need them. Throws a not-supported error on
3708
+ * the WASM backend.
3709
+ *
3710
+ * @returns the number of points the server reports as inserted.
3711
+ */
3712
+ async upsertBatchRaw(collection, docs) {
3713
+ this.ensureInitialized();
3714
+ validateDocsBatch(docs, (doc) => {
3715
+ validateDocument(doc, this.config);
3716
+ });
3717
+ return this.backend.upsertBatchRaw(collection, docs);
3718
+ }
3504
3719
  async delete(collection, id) {
3505
3720
  this.ensureInitialized();
3506
3721
  validateRestPointId(id, this.config);
@@ -3548,6 +3763,11 @@ var VelesDB = class {
3548
3763
  this.ensureInitialized();
3549
3764
  return multiQuerySearch2(this.backend, collection, vectors, options);
3550
3765
  }
3766
+ /** Multi-query fusion search returning only IDs and scores (no payloads). */
3767
+ async multiQuerySearchIds(collection, vectors, options) {
3768
+ this.ensureInitialized();
3769
+ return multiQuerySearchIds2(this.backend, collection, vectors, options);
3770
+ }
3551
3771
  /**
3552
3772
  * Pure sparse search against a named sparse index.
3553
3773
  *
@@ -3578,6 +3798,10 @@ var VelesDB = class {
3578
3798
  this.ensureInitialized();
3579
3799
  return trainPq2(this.backend, collection, options);
3580
3800
  }
3801
+ async enableStreaming(collection, config) {
3802
+ this.ensureInitialized();
3803
+ return enableStreaming2(this.backend, collection, config);
3804
+ }
3581
3805
  async streamInsert(collection, docs) {
3582
3806
  this.ensureInitialized();
3583
3807
  return streamInsert2(this.backend, this.config, collection, docs);
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,6 +59,7 @@ 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
65
  velesqlQuery: false,
@@ -752,6 +754,9 @@ function validateCollectionName(name) {
752
754
  );
753
755
  }
754
756
  }
757
+ async function safeJsonParse(response) {
758
+ return response.json().catch(() => ({}));
759
+ }
755
760
  function toNumberArray(v) {
756
761
  return v instanceof Float32Array ? Array.from(v) : v;
757
762
  }
@@ -805,12 +810,18 @@ async function wasmScroll(_collection, _request) {
805
810
  async function wasmTrainPq(_collection, _options) {
806
811
  wasmNotSupported("PQ training");
807
812
  }
813
+ async function wasmEnableStreaming(_collection, _config) {
814
+ wasmNotSupported("Streaming enable");
815
+ }
808
816
  async function wasmStreamInsert(_collection, _docs) {
809
817
  wasmNotSupported("Streaming insert");
810
818
  }
811
819
  async function wasmStreamUpsertPoints(_collection, _docs) {
812
820
  wasmNotSupported("Streaming batch upsert");
813
821
  }
822
+ async function wasmUpsertBatchRaw(_collection, _docs) {
823
+ wasmNotSupported("Binary bulk upsert (upsertBatchRaw)");
824
+ }
814
825
  async function wasmCreateGraphCollection(_name, _config) {
815
826
  wasmNotSupported("Graph collections");
816
827
  }
@@ -826,6 +837,9 @@ async function wasmGetCollectionConfig(_collection) {
826
837
  async function wasmSearchIds(_collection, _query, _options) {
827
838
  wasmNotSupported("searchIds");
828
839
  }
840
+ async function wasmMultiQuerySearchIds(_collection, _vectors, _options) {
841
+ wasmNotSupported("multiQuerySearchIds");
842
+ }
829
843
  async function wasmStoreSemanticFact(_collection, _entry) {
830
844
  wasmNotSupported("Agent memory");
831
845
  }
@@ -1082,6 +1096,9 @@ var WasmBackend = class {
1082
1096
  }
1083
1097
  }
1084
1098
  }
1099
+ async upsertBatchRaw(c, d) {
1100
+ return wasmUpsertBatchRaw(c, d);
1101
+ }
1085
1102
  async delete(collectionName, id) {
1086
1103
  this.ensureInitialized();
1087
1104
  const collection = this.collections.get(collectionName);
@@ -1213,6 +1230,10 @@ var WasmBackend = class {
1213
1230
  this.ensureInitialized();
1214
1231
  return wasmTrainPq(c, o);
1215
1232
  }
1233
+ async enableStreaming(c, cfg) {
1234
+ this.ensureInitialized();
1235
+ return wasmEnableStreaming(c, cfg);
1236
+ }
1216
1237
  async streamInsert(c, d) {
1217
1238
  this.ensureInitialized();
1218
1239
  return wasmStreamInsert(c, d);
@@ -1241,6 +1262,10 @@ var WasmBackend = class {
1241
1262
  this.ensureInitialized();
1242
1263
  return wasmSearchIds(c, q, o);
1243
1264
  }
1265
+ async multiQuerySearchIds(c, v, o) {
1266
+ this.ensureInitialized();
1267
+ return wasmMultiQuerySearchIds(c, v, o);
1268
+ }
1244
1269
  async storeSemanticFact(c, e) {
1245
1270
  this.ensureInitialized();
1246
1271
  return wasmStoreSemanticFact(c, e);
@@ -1345,6 +1370,9 @@ var WasmBackend = class {
1345
1370
  };
1346
1371
 
1347
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;
1348
1376
  var U64_MAX = 18446744073709551615n;
1349
1377
  function coerceDecimalStringId(id) {
1350
1378
  if (!/^\d+$/.test(id)) return NaN;
@@ -1495,6 +1523,105 @@ async function flush(transport, collection) {
1495
1523
  );
1496
1524
  throwOnError(response, `Collection '${collection}'`);
1497
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
+ }
1498
1625
 
1499
1626
  // src/backends/rest-http.ts
1500
1627
  var STATUS_ERROR_CODES = {
@@ -1565,7 +1692,7 @@ async function request(config, method, path, body) {
1565
1692
  signal: controller.signal
1566
1693
  });
1567
1694
  clearTimeout(timeoutId);
1568
- const data = await response.json().catch(() => ({}));
1695
+ const data = await safeJsonParse(response);
1569
1696
  if (!response.ok) {
1570
1697
  const ep = extractErrorPayload(data);
1571
1698
  return { error: {
@@ -1589,6 +1716,13 @@ function buildCrudTransport(config) {
1589
1716
  requestJson: (m, p, b) => request(config, m, p, b)
1590
1717
  };
1591
1718
  }
1719
+ function buildRawBulkTransport(config) {
1720
+ return {
1721
+ baseUrl: config.baseUrl,
1722
+ apiKey: config.apiKey,
1723
+ timeout: config.timeout
1724
+ };
1725
+ }
1592
1726
  function buildSearchTransport(config) {
1593
1727
  return {
1594
1728
  requestJson: (m, p, b) => request(config, m, p, b),
@@ -2076,6 +2210,22 @@ async function multiQuerySearch(transport, collection, vectors, options) {
2076
2210
  throwOnError(response, `Collection '${collection}'`);
2077
2211
  return response.data?.results ?? [];
2078
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
+ }
2079
2229
  async function sparseSearchNamed(transport, collection, query3, indexName, options) {
2080
2230
  const body = {
2081
2231
  sparse_vectors: { [indexName]: transport.sparseToRest(query3) },
@@ -2293,7 +2443,7 @@ async function query(transport, collection, queryString, params, options) {
2293
2443
  );
2294
2444
  throwOnError(response, `Collection '${collection}'`);
2295
2445
  const rawData = response.data;
2296
- if (rawData && Object.prototype.hasOwnProperty.call(rawData, "result")) {
2446
+ if (rawData != null && Object.prototype.hasOwnProperty.call(rawData, "result")) {
2297
2447
  return {
2298
2448
  result: rawData.result,
2299
2449
  stats: {
@@ -2563,7 +2713,7 @@ async function streamInsert(transport, collection, docs) {
2563
2713
  throw new BackpressureError();
2564
2714
  }
2565
2715
  if (!response.ok && response.status !== 202) {
2566
- const data = await response.json().catch(() => ({}));
2716
+ const data = await safeJsonParse(response);
2567
2717
  const errorPayload = transport.extractErrorPayload(data);
2568
2718
  throw new VelesDBError(
2569
2719
  errorPayload.message ?? `HTTP ${response.status}`,
@@ -2585,6 +2735,24 @@ async function streamInsert(transport, collection, docs) {
2585
2735
  }
2586
2736
  }
2587
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
+ }
2588
2756
  function requireSafeRangeId(restId) {
2589
2757
  if (typeof restId === "string") {
2590
2758
  throw new ValidationError(
@@ -2629,14 +2797,14 @@ async function streamUpsertPoints(transport, collection, docs) {
2629
2797
  throw new BackpressureError();
2630
2798
  }
2631
2799
  if (!response.ok) {
2632
- const data2 = await response.json().catch(() => ({}));
2800
+ const data2 = await safeJsonParse(response);
2633
2801
  const errorPayload = transport.extractErrorPayload(data2);
2634
2802
  throw new VelesDBError(
2635
2803
  errorPayload.message ?? `HTTP ${response.status}`,
2636
2804
  errorPayload.code ?? transport.mapStatusToErrorCode(response.status)
2637
2805
  );
2638
2806
  }
2639
- const data = await response.json().catch(() => ({}));
2807
+ const data = await safeJsonParse(response);
2640
2808
  return {
2641
2809
  message: typeof data.message === "string" ? data.message : "Stream processed",
2642
2810
  inserted: typeof data.inserted === "number" ? data.inserted : 0,
@@ -2721,6 +2889,10 @@ var RestBackend = class {
2721
2889
  this.ensureInitialized();
2722
2890
  return upsertBatch(buildCrudTransport(this.httpConfig), c, d);
2723
2891
  }
2892
+ async upsertBatchRaw(c, d) {
2893
+ this.ensureInitialized();
2894
+ return upsertBatchRaw(buildRawBulkTransport(this.httpConfig), c, d, d[0]?.vector.length ?? 0);
2895
+ }
2724
2896
  async delete(c, id) {
2725
2897
  this.ensureInitialized();
2726
2898
  return deletePoint(buildCrudTransport(this.httpConfig), c, id);
@@ -2823,6 +2995,10 @@ var RestBackend = class {
2823
2995
  this.ensureInitialized();
2824
2996
  return multiQuerySearch(buildSearchTransport(this.httpConfig), c, v, o);
2825
2997
  }
2998
+ async multiQuerySearchIds(c, v, o) {
2999
+ this.ensureInitialized();
3000
+ return multiQuerySearchIds(buildSearchTransport(this.httpConfig), c, v, o);
3001
+ }
2826
3002
  async searchIds(c, q, o) {
2827
3003
  this.ensureInitialized();
2828
3004
  return searchIds(buildSearchTransport(this.httpConfig), c, q, o);
@@ -2909,6 +3085,10 @@ var RestBackend = class {
2909
3085
  this.ensureInitialized();
2910
3086
  return trainPq(buildStreamingTransport(this.httpConfig), c, o);
2911
3087
  }
3088
+ async enableStreaming(c, cfg) {
3089
+ this.ensureInitialized();
3090
+ return enableStreaming(buildStreamingTransport(this.httpConfig), c, cfg);
3091
+ }
2912
3092
  async streamInsert(c, d) {
2913
3093
  this.ensureInitialized();
2914
3094
  return streamInsert(buildStreamingTransport(this.httpConfig), c, d);
@@ -3091,9 +3271,21 @@ function multiQuerySearch2(backend, collection, vectors, options) {
3091
3271
  }
3092
3272
  return backend.multiQuerySearch(collection, vectors, options);
3093
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
+ }
3094
3283
  function trainPq2(backend, collection, options) {
3095
3284
  return backend.trainPq(collection, options);
3096
3285
  }
3286
+ function enableStreaming2(backend, collection, config) {
3287
+ return backend.enableStreaming(collection, config);
3288
+ }
3097
3289
  function streamInsert2(backend, config, collection, docs) {
3098
3290
  validateDocsBatch(docs, (doc) => {
3099
3291
  validateDocument(doc, config);
@@ -3362,6 +3554,24 @@ var VelesDB = class {
3362
3554
  });
3363
3555
  await this.backend.upsertBatch(collection, docs);
3364
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
+ }
3365
3575
  async delete(collection, id) {
3366
3576
  this.ensureInitialized();
3367
3577
  validateRestPointId(id, this.config);
@@ -3409,6 +3619,11 @@ var VelesDB = class {
3409
3619
  this.ensureInitialized();
3410
3620
  return multiQuerySearch2(this.backend, collection, vectors, options);
3411
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
+ }
3412
3627
  /**
3413
3628
  * Pure sparse search against a named sparse index.
3414
3629
  *
@@ -3439,6 +3654,10 @@ var VelesDB = class {
3439
3654
  this.ensureInitialized();
3440
3655
  return trainPq2(this.backend, collection, options);
3441
3656
  }
3657
+ async enableStreaming(collection, config) {
3658
+ this.ensureInitialized();
3659
+ return enableStreaming2(this.backend, collection, config);
3660
+ }
3442
3661
  async streamInsert(collection, docs) {
3443
3662
  this.ensureInitialized();
3444
3663
  return streamInsert2(this.backend, this.config, collection, docs);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wiscale/velesdb-sdk",
3
- "version": "2.0.0",
3
+ "version": "3.0.1",
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",
@@ -69,12 +69,13 @@
69
69
  "vitest": "^4.0.16"
70
70
  },
71
71
  "dependencies": {
72
- "@wiscale/velesdb-wasm": "^1.4.1"
72
+ "@wiscale/velesdb-wasm": "^2.0.0"
73
73
  },
74
74
  "engines": {
75
75
  "node": ">=18.0.0"
76
76
  },
77
77
  "overrides": {
78
- "minimatch": "^9.0.7"
78
+ "minimatch": "^9.0.7",
79
+ "esbuild": ">=0.28.1"
79
80
  }
80
81
  }