Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
133
vendor/ruvector/npm/packages/rvf/src/backend.d.ts
vendored
Normal file
133
vendor/ruvector/npm/packages/rvf/src/backend.d.ts
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
import type { RvfOptions, RvfQueryOptions, RvfSearchResult, RvfIngestResult, RvfIngestEntry, RvfDeleteResult, RvfCompactionResult, RvfStatus, RvfFilterExpr, RvfKernelData, RvfEbpfData, RvfSegmentInfo, BackendType } from './types';
|
||||
/**
|
||||
* Abstract backend that wraps either the native (N-API) or WASM build of
|
||||
* rvf-runtime. The `RvfDatabase` class delegates all I/O to a backend
|
||||
* instance, keeping the public API identical regardless of runtime.
|
||||
*/
|
||||
export interface RvfBackend {
|
||||
/** Create a new store file at `path` with the given options. */
|
||||
create(path: string, options: RvfOptions): Promise<void>;
|
||||
/** Open an existing store at `path` for read-write access. */
|
||||
open(path: string): Promise<void>;
|
||||
/** Open an existing store at `path` for read-only access. */
|
||||
openReadonly(path: string): Promise<void>;
|
||||
/** Ingest a batch of vectors. */
|
||||
ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult>;
|
||||
/** Query the k nearest neighbors. */
|
||||
query(vector: Float32Array, k: number, options?: RvfQueryOptions): Promise<RvfSearchResult[]>;
|
||||
/** Soft-delete vectors by ID. */
|
||||
delete(ids: string[]): Promise<RvfDeleteResult>;
|
||||
/** Soft-delete vectors matching a filter. */
|
||||
deleteByFilter(filter: RvfFilterExpr): Promise<RvfDeleteResult>;
|
||||
/** Run compaction to reclaim dead space. */
|
||||
compact(): Promise<RvfCompactionResult>;
|
||||
/** Get the current store status. */
|
||||
status(): Promise<RvfStatus>;
|
||||
/** Close the store, releasing locks. */
|
||||
close(): Promise<void>;
|
||||
fileId(): Promise<string>;
|
||||
parentId(): Promise<string>;
|
||||
lineageDepth(): Promise<number>;
|
||||
derive(childPath: string, options?: RvfOptions): Promise<RvfBackend>;
|
||||
embedKernel(arch: number, kernelType: number, flags: number, image: Uint8Array, apiPort: number, cmdline?: string): Promise<number>;
|
||||
extractKernel(): Promise<RvfKernelData | null>;
|
||||
embedEbpf(programType: number, attachType: number, maxDimension: number, bytecode: Uint8Array, btf?: Uint8Array): Promise<number>;
|
||||
extractEbpf(): Promise<RvfEbpfData | null>;
|
||||
segments(): Promise<RvfSegmentInfo[]>;
|
||||
dimension(): Promise<number>;
|
||||
}
|
||||
/**
|
||||
* Backend that delegates to the `@ruvector/rvf-node` native N-API addon.
|
||||
*
|
||||
* The native addon is loaded lazily on first use so that the SDK package can
|
||||
* be imported in environments where the native build is unavailable (e.g.
|
||||
* browsers) without throwing at import time.
|
||||
*/
|
||||
export declare class NodeBackend implements RvfBackend {
|
||||
private native;
|
||||
private handle;
|
||||
private idToLabel;
|
||||
private labelToId;
|
||||
private nextLabel;
|
||||
private storePath;
|
||||
private loadNative;
|
||||
private ensureHandle;
|
||||
create(path: string, options: RvfOptions): Promise<void>;
|
||||
open(path: string): Promise<void>;
|
||||
openReadonly(path: string): Promise<void>;
|
||||
ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult>;
|
||||
query(vector: Float32Array, k: number, options?: RvfQueryOptions): Promise<RvfSearchResult[]>;
|
||||
delete(ids: string[]): Promise<RvfDeleteResult>;
|
||||
deleteByFilter(filter: RvfFilterExpr): Promise<RvfDeleteResult>;
|
||||
compact(): Promise<RvfCompactionResult>;
|
||||
status(): Promise<RvfStatus>;
|
||||
close(): Promise<void>;
|
||||
fileId(): Promise<string>;
|
||||
parentId(): Promise<string>;
|
||||
lineageDepth(): Promise<number>;
|
||||
derive(childPath: string, options?: RvfOptions): Promise<RvfBackend>;
|
||||
embedKernel(arch: number, kernelType: number, flags: number, image: Uint8Array, apiPort: number, cmdline?: string): Promise<number>;
|
||||
extractKernel(): Promise<RvfKernelData | null>;
|
||||
embedEbpf(programType: number, attachType: number, maxDimension: number, bytecode: Uint8Array, btf?: Uint8Array): Promise<number>;
|
||||
extractEbpf(): Promise<RvfEbpfData | null>;
|
||||
segments(): Promise<RvfSegmentInfo[]>;
|
||||
dimension(): Promise<number>;
|
||||
/**
|
||||
* Get or allocate a numeric label for a string ID.
|
||||
* If the ID was already seen, returns the existing label.
|
||||
*/
|
||||
private resolveLabel;
|
||||
/** Path to the sidecar mappings file. */
|
||||
private mappingsPath;
|
||||
/** Persist the string↔label mapping to a sidecar JSON file. */
|
||||
private saveMappings;
|
||||
/** Load the string↔label mapping from the sidecar JSON file if it exists. */
|
||||
private loadMappings;
|
||||
}
|
||||
/**
|
||||
* Backend that delegates to the `@ruvector/rvf-wasm` WASM build.
|
||||
*
|
||||
* The WASM microkernel exposes C-ABI store functions (`rvf_store_create`,
|
||||
* `rvf_store_query`, etc.) operating on integer handles. This backend wraps
|
||||
* them behind the same `RvfBackend` interface.
|
||||
*
|
||||
* Suitable for browser environments. The WASM module is loaded lazily.
|
||||
*/
|
||||
export declare class WasmBackend implements RvfBackend {
|
||||
private wasm;
|
||||
/** Integer store handle returned by `rvf_store_create` / `rvf_store_open`. */
|
||||
private handle;
|
||||
private dim;
|
||||
private loadWasm;
|
||||
private ensureHandle;
|
||||
private metricCode;
|
||||
create(_path: string, options: RvfOptions): Promise<void>;
|
||||
open(_path: string): Promise<void>;
|
||||
openReadonly(_path: string): Promise<void>;
|
||||
ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult>;
|
||||
query(vector: Float32Array, k: number, _options?: RvfQueryOptions): Promise<RvfSearchResult[]>;
|
||||
delete(ids: string[]): Promise<RvfDeleteResult>;
|
||||
deleteByFilter(_filter: RvfFilterExpr): Promise<RvfDeleteResult>;
|
||||
compact(): Promise<RvfCompactionResult>;
|
||||
status(): Promise<RvfStatus>;
|
||||
close(): Promise<void>;
|
||||
fileId(): Promise<string>;
|
||||
parentId(): Promise<string>;
|
||||
lineageDepth(): Promise<number>;
|
||||
derive(_childPath: string, _options?: RvfOptions): Promise<RvfBackend>;
|
||||
embedKernel(): Promise<number>;
|
||||
extractKernel(): Promise<RvfKernelData | null>;
|
||||
embedEbpf(): Promise<number>;
|
||||
extractEbpf(): Promise<RvfEbpfData | null>;
|
||||
segments(): Promise<RvfSegmentInfo[]>;
|
||||
dimension(): Promise<number>;
|
||||
}
|
||||
/**
|
||||
* Resolve a `BackendType` to a concrete `RvfBackend` instance.
|
||||
*
|
||||
* - `'node'` Always returns a `NodeBackend`.
|
||||
* - `'wasm'` Always returns a `WasmBackend`.
|
||||
* - `'auto'` Tries `node` first, falls back to `wasm`.
|
||||
*/
|
||||
export declare function resolveBackend(type: BackendType): RvfBackend;
|
||||
//# sourceMappingURL=backend.d.ts.map
|
||||
1
vendor/ruvector/npm/packages/rvf/src/backend.d.ts.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/backend.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["backend.ts"],"names":[],"mappings":"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"}
|
||||
731
vendor/ruvector/npm/packages/rvf/src/backend.js
vendored
Normal file
731
vendor/ruvector/npm/packages/rvf/src/backend.js
vendored
Normal file
@@ -0,0 +1,731 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WasmBackend = exports.NodeBackend = void 0;
|
||||
exports.resolveBackend = resolveBackend;
|
||||
const errors_1 = require("./errors");
|
||||
// ---------------------------------------------------------------------------
|
||||
// NodeBackend — wraps @ruvector/rvf-node (N-API)
|
||||
// ---------------------------------------------------------------------------
|
||||
/**
|
||||
* Backend that delegates to the `@ruvector/rvf-node` native N-API addon.
|
||||
*
|
||||
* The native addon is loaded lazily on first use so that the SDK package can
|
||||
* be imported in environments where the native build is unavailable (e.g.
|
||||
* browsers) without throwing at import time.
|
||||
*/
|
||||
class NodeBackend {
|
||||
constructor() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
this.native = null;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
this.handle = null;
|
||||
// String ID <-> Numeric Label mappings (N-API layer requires i64 labels)
|
||||
this.idToLabel = new Map();
|
||||
this.labelToId = new Map();
|
||||
this.nextLabel = 1; // RVF uses 1-based labels
|
||||
this.storePath = '';
|
||||
}
|
||||
async loadNative() {
|
||||
if (this.native)
|
||||
return;
|
||||
try {
|
||||
// Dynamic import so the SDK can be bundled for browsers without
|
||||
// pulling in the native addon at compile time.
|
||||
// The NAPI addon exports a `RvfDatabase` class with factory methods.
|
||||
const mod = await Promise.resolve().then(() => __importStar(require('@ruvector/rvf-node')));
|
||||
this.native = mod.RvfDatabase ?? mod.default?.RvfDatabase ?? mod;
|
||||
}
|
||||
catch {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'Could not load @ruvector/rvf-node — is it installed?');
|
||||
}
|
||||
}
|
||||
ensureHandle() {
|
||||
if (!this.handle) {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.StoreClosed);
|
||||
}
|
||||
}
|
||||
async create(path, options) {
|
||||
await this.loadNative();
|
||||
try {
|
||||
this.handle = await this.native.create(path, mapOptionsToNative(options));
|
||||
this.storePath = path;
|
||||
this.idToLabel.clear();
|
||||
this.labelToId.clear();
|
||||
this.nextLabel = 1;
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async open(path) {
|
||||
await this.loadNative();
|
||||
try {
|
||||
this.handle = await this.native.open(path);
|
||||
this.storePath = path;
|
||||
await this.loadMappings();
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async openReadonly(path) {
|
||||
await this.loadNative();
|
||||
try {
|
||||
this.handle = await this.native.openReadonly(path);
|
||||
this.storePath = path;
|
||||
await this.loadMappings();
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async ingestBatch(entries) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
// NAPI signature: ingestBatch(vectors: Float32Array, ids: i64[], metadata?)
|
||||
// Flatten individual vectors into a single contiguous Float32Array.
|
||||
const n = entries.length;
|
||||
if (n === 0)
|
||||
return { accepted: 0, rejected: 0, epoch: 0 };
|
||||
const first = entries[0].vector;
|
||||
const dim = first instanceof Float32Array ? first.length : first.length;
|
||||
const flat = new Float32Array(n * dim);
|
||||
for (let i = 0; i < n; i++) {
|
||||
const v = entries[i].vector;
|
||||
const f32 = v instanceof Float32Array ? v : new Float32Array(v);
|
||||
flat.set(f32, i * dim);
|
||||
}
|
||||
// Map string IDs to numeric labels for the N-API layer.
|
||||
// The native Rust HNSW expects i64 labels — non-numeric strings cause
|
||||
// silent data loss (NaN → dropped). We maintain a bidirectional
|
||||
// string↔label mapping and persist it as a sidecar JSON file.
|
||||
const ids = entries.map((e) => this.resolveLabel(e.id));
|
||||
const result = this.handle.ingestBatch(flat, ids);
|
||||
// Persist mappings after every ingest so they survive crashes.
|
||||
await this.saveMappings();
|
||||
return {
|
||||
accepted: Number(result.accepted),
|
||||
rejected: Number(result.rejected),
|
||||
epoch: result.epoch,
|
||||
};
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async query(vector, k, options) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const nativeOpts = options ? mapQueryOptionsToNative(options) : undefined;
|
||||
const results = this.handle.query(vector, k, nativeOpts);
|
||||
// Map numeric labels back to original string IDs.
|
||||
return results.map((r) => ({
|
||||
id: this.labelToId.get(Number(r.id)) ?? String(r.id),
|
||||
distance: r.distance,
|
||||
}));
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async delete(ids) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
// Resolve string IDs to numeric labels for the N-API layer.
|
||||
const numIds = ids
|
||||
.map((id) => this.idToLabel.get(id))
|
||||
.filter((label) => label !== undefined);
|
||||
if (numIds.length === 0) {
|
||||
return { deleted: 0, epoch: 0 };
|
||||
}
|
||||
const result = this.handle.delete(numIds);
|
||||
// Remove deleted entries from the mapping.
|
||||
for (const id of ids) {
|
||||
const label = this.idToLabel.get(id);
|
||||
if (label !== undefined) {
|
||||
this.idToLabel.delete(id);
|
||||
this.labelToId.delete(label);
|
||||
}
|
||||
}
|
||||
await this.saveMappings();
|
||||
return { deleted: Number(result.deleted), epoch: result.epoch };
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async deleteByFilter(filter) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
// NAPI takes a JSON string for the filter expression.
|
||||
const result = this.handle.deleteByFilter(JSON.stringify(filter));
|
||||
return { deleted: Number(result.deleted), epoch: result.epoch };
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async compact() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const result = this.handle.compact();
|
||||
return {
|
||||
segmentsCompacted: result.segmentsCompacted ?? result.segments_compacted,
|
||||
bytesReclaimed: Number(result.bytesReclaimed ?? result.bytes_reclaimed),
|
||||
epoch: result.epoch,
|
||||
};
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async status() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const s = this.handle.status();
|
||||
return mapNativeStatus(s);
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async close() {
|
||||
if (!this.handle)
|
||||
return;
|
||||
try {
|
||||
await this.saveMappings();
|
||||
this.handle.close();
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
finally {
|
||||
this.handle = null;
|
||||
this.idToLabel.clear();
|
||||
this.labelToId.clear();
|
||||
this.nextLabel = 1;
|
||||
this.storePath = '';
|
||||
}
|
||||
}
|
||||
async fileId() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.fileId();
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async parentId() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.parentId();
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async lineageDepth() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.lineageDepth();
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async derive(childPath, options) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const nativeOpts = options ? mapOptionsToNative(options) : undefined;
|
||||
const childHandle = this.handle.derive(childPath, nativeOpts);
|
||||
const child = new NodeBackend();
|
||||
child.native = this.native;
|
||||
child.handle = childHandle;
|
||||
child.storePath = childPath;
|
||||
// Copy parent mappings to child (COW semantics)
|
||||
child.idToLabel = new Map(this.idToLabel);
|
||||
child.labelToId = new Map(this.labelToId);
|
||||
child.nextLabel = this.nextLabel;
|
||||
await child.saveMappings();
|
||||
return child;
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async embedKernel(arch, kernelType, flags, image, apiPort, cmdline) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.embedKernel(arch, kernelType, flags, Buffer.from(image), apiPort, cmdline);
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async extractKernel() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const result = this.handle.extractKernel();
|
||||
if (!result)
|
||||
return null;
|
||||
return {
|
||||
header: new Uint8Array(result.header),
|
||||
image: new Uint8Array(result.image),
|
||||
};
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async embedEbpf(programType, attachType, maxDimension, bytecode, btf) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.embedEbpf(programType, attachType, maxDimension, Buffer.from(bytecode), btf ? Buffer.from(btf) : undefined);
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async extractEbpf() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const result = this.handle.extractEbpf();
|
||||
if (!result)
|
||||
return null;
|
||||
return {
|
||||
header: new Uint8Array(result.header),
|
||||
payload: new Uint8Array(result.payload),
|
||||
};
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async segments() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const segs = this.handle.segments();
|
||||
return segs.map((s) => ({
|
||||
id: s.id,
|
||||
offset: s.offset,
|
||||
payloadLength: s.payloadLength ?? s.payload_length,
|
||||
segType: s.segType ?? s.seg_type,
|
||||
}));
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async dimension() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.dimension();
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
// ─── String ID ↔ Numeric Label mapping helpers ───
|
||||
/**
|
||||
* Get or allocate a numeric label for a string ID.
|
||||
* If the ID was already seen, returns the existing label.
|
||||
*/
|
||||
resolveLabel(id) {
|
||||
let label = this.idToLabel.get(id);
|
||||
if (label !== undefined)
|
||||
return label;
|
||||
label = this.nextLabel++;
|
||||
this.idToLabel.set(id, label);
|
||||
this.labelToId.set(label, id);
|
||||
return label;
|
||||
}
|
||||
/** Path to the sidecar mappings file. */
|
||||
mappingsPath() {
|
||||
return this.storePath ? this.storePath + '.idmap.json' : '';
|
||||
}
|
||||
/** Persist the string↔label mapping to a sidecar JSON file. */
|
||||
async saveMappings() {
|
||||
const mp = this.mappingsPath();
|
||||
if (!mp)
|
||||
return;
|
||||
try {
|
||||
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
||||
const data = JSON.stringify({
|
||||
idToLabel: Object.fromEntries(this.idToLabel),
|
||||
labelToId: Object.fromEntries(Array.from(this.labelToId.entries()).map(([k, v]) => [String(k), v])),
|
||||
nextLabel: this.nextLabel,
|
||||
});
|
||||
fs.writeFileSync(mp, data, 'utf-8');
|
||||
}
|
||||
catch {
|
||||
// Non-fatal: mapping persistence is best-effort (e.g. read-only FS).
|
||||
}
|
||||
}
|
||||
/** Load the string↔label mapping from the sidecar JSON file if it exists. */
|
||||
async loadMappings() {
|
||||
const mp = this.mappingsPath();
|
||||
if (!mp)
|
||||
return;
|
||||
try {
|
||||
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
||||
if (!fs.existsSync(mp))
|
||||
return;
|
||||
const raw = JSON.parse(fs.readFileSync(mp, 'utf-8'));
|
||||
this.idToLabel = new Map(Object.entries(raw.idToLabel ?? {}).map(([k, v]) => [k, Number(v)]));
|
||||
this.labelToId = new Map(Object.entries(raw.labelToId ?? {}).map(([k, v]) => [Number(k), v]));
|
||||
this.nextLabel = raw.nextLabel ?? this.idToLabel.size + 1;
|
||||
}
|
||||
catch {
|
||||
// Non-fatal: start with empty mappings.
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.NodeBackend = NodeBackend;
|
||||
// ---------------------------------------------------------------------------
|
||||
// WasmBackend — wraps @ruvector/rvf-wasm
|
||||
// ---------------------------------------------------------------------------
|
||||
/**
|
||||
* Backend that delegates to the `@ruvector/rvf-wasm` WASM build.
|
||||
*
|
||||
* The WASM microkernel exposes C-ABI store functions (`rvf_store_create`,
|
||||
* `rvf_store_query`, etc.) operating on integer handles. This backend wraps
|
||||
* them behind the same `RvfBackend` interface.
|
||||
*
|
||||
* Suitable for browser environments. The WASM module is loaded lazily.
|
||||
*/
|
||||
class WasmBackend {
|
||||
constructor() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
this.wasm = null;
|
||||
/** Integer store handle returned by `rvf_store_create` / `rvf_store_open`. */
|
||||
this.handle = 0;
|
||||
this.dim = 0;
|
||||
}
|
||||
async loadWasm() {
|
||||
if (this.wasm)
|
||||
return;
|
||||
try {
|
||||
const mod = await Promise.resolve().then(() => __importStar(require('@ruvector/rvf-wasm')));
|
||||
// wasm-pack default export is the init function
|
||||
if (typeof mod.default === 'function') {
|
||||
this.wasm = await mod.default();
|
||||
}
|
||||
else {
|
||||
this.wasm = mod;
|
||||
}
|
||||
}
|
||||
catch {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'Could not load @ruvector/rvf-wasm — is it installed?');
|
||||
}
|
||||
}
|
||||
ensureHandle() {
|
||||
if (!this.handle) {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.StoreClosed);
|
||||
}
|
||||
}
|
||||
metricCode(metric) {
|
||||
switch (metric) {
|
||||
case 'Cosine': return 2;
|
||||
case 'InnerProduct': return 1;
|
||||
default: return 0; // L2
|
||||
}
|
||||
}
|
||||
async create(_path, options) {
|
||||
await this.loadWasm();
|
||||
try {
|
||||
const nativeOpts = mapOptionsToNative(options);
|
||||
const dim = nativeOpts.dimension;
|
||||
const metric = this.metricCode(nativeOpts.metric);
|
||||
const h = this.wasm.rvf_store_create(dim, metric);
|
||||
if (h <= 0)
|
||||
throw new Error('rvf_store_create returned ' + h);
|
||||
this.handle = h;
|
||||
this.dim = dim;
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async open(_path) {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'WASM backend does not support file-based open (in-memory only)');
|
||||
}
|
||||
async openReadonly(_path) {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'WASM backend does not support file-based openReadonly (in-memory only)');
|
||||
}
|
||||
async ingestBatch(entries) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const n = entries.length;
|
||||
if (n === 0)
|
||||
return { accepted: 0, rejected: 0, epoch: 0 };
|
||||
const dim = this.dim || (entries[0].vector instanceof Float32Array
|
||||
? entries[0].vector.length : entries[0].vector.length);
|
||||
const flat = new Float32Array(n * dim);
|
||||
const ids = new BigUint64Array(n);
|
||||
for (let i = 0; i < n; i++) {
|
||||
const v = entries[i].vector;
|
||||
const f32 = v instanceof Float32Array ? v : new Float32Array(v);
|
||||
flat.set(f32, i * dim);
|
||||
ids[i] = BigInt(entries[i].id);
|
||||
}
|
||||
// Allocate in WASM memory and call
|
||||
const vecsPtr = this.wasm.rvf_alloc(flat.byteLength);
|
||||
const idsPtr = this.wasm.rvf_alloc(ids.byteLength);
|
||||
new Float32Array(this.wasm.memory.buffer, vecsPtr, flat.length).set(flat);
|
||||
new BigUint64Array(this.wasm.memory.buffer, idsPtr, ids.length).set(ids);
|
||||
const accepted = this.wasm.rvf_store_ingest(this.handle, vecsPtr, idsPtr, n);
|
||||
this.wasm.rvf_free(vecsPtr, flat.byteLength);
|
||||
this.wasm.rvf_free(idsPtr, ids.byteLength);
|
||||
return { accepted: accepted > 0 ? accepted : 0, rejected: accepted < 0 ? n : 0, epoch: 0 };
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async query(vector, k, _options) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const queryPtr = this.wasm.rvf_alloc(vector.byteLength);
|
||||
new Float32Array(this.wasm.memory.buffer, queryPtr, vector.length).set(vector);
|
||||
// Each result = 8 bytes id + 4 bytes dist = 12 bytes
|
||||
const outSize = k * 12;
|
||||
const outPtr = this.wasm.rvf_alloc(outSize);
|
||||
const count = this.wasm.rvf_store_query(this.handle, queryPtr, k, 0, outPtr);
|
||||
const results = [];
|
||||
const view = new DataView(this.wasm.memory.buffer);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const off = outPtr + i * 12;
|
||||
const id = view.getBigUint64(off, true);
|
||||
const dist = view.getFloat32(off + 8, true);
|
||||
results.push({ id: String(id), distance: dist });
|
||||
}
|
||||
this.wasm.rvf_free(queryPtr, vector.byteLength);
|
||||
this.wasm.rvf_free(outPtr, outSize);
|
||||
return results;
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async delete(ids) {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const arr = new BigUint64Array(ids.map((id) => BigInt(id)));
|
||||
const ptr = this.wasm.rvf_alloc(arr.byteLength);
|
||||
new BigUint64Array(this.wasm.memory.buffer, ptr, arr.length).set(arr);
|
||||
const deleted = this.wasm.rvf_store_delete(this.handle, ptr, ids.length);
|
||||
this.wasm.rvf_free(ptr, arr.byteLength);
|
||||
return { deleted: deleted > 0 ? deleted : 0, epoch: 0 };
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async deleteByFilter(_filter) {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'deleteByFilter not supported in WASM backend');
|
||||
}
|
||||
async compact() {
|
||||
return { segmentsCompacted: 0, bytesReclaimed: 0, epoch: 0 };
|
||||
}
|
||||
async status() {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const outPtr = this.wasm.rvf_alloc(20);
|
||||
this.wasm.rvf_store_status(this.handle, outPtr);
|
||||
const view = new DataView(this.wasm.memory.buffer);
|
||||
const totalVectors = view.getUint32(outPtr, true);
|
||||
const dim = view.getUint32(outPtr + 4, true);
|
||||
this.wasm.rvf_free(outPtr, 20);
|
||||
return {
|
||||
totalVectors,
|
||||
totalSegments: 1,
|
||||
fileSizeBytes: 0,
|
||||
epoch: 0,
|
||||
profileId: 0,
|
||||
compactionState: 'idle',
|
||||
deadSpaceRatio: 0,
|
||||
readOnly: false,
|
||||
};
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
async close() {
|
||||
if (!this.handle)
|
||||
return;
|
||||
try {
|
||||
this.wasm.rvf_store_close(this.handle);
|
||||
}
|
||||
catch (err) {
|
||||
throw errors_1.RvfError.fromNative(err);
|
||||
}
|
||||
finally {
|
||||
this.handle = 0;
|
||||
}
|
||||
}
|
||||
async fileId() {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'fileId not supported in WASM backend');
|
||||
}
|
||||
async parentId() {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'parentId not supported in WASM backend');
|
||||
}
|
||||
async lineageDepth() {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'lineageDepth not supported in WASM backend');
|
||||
}
|
||||
async derive(_childPath, _options) {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'derive not supported in WASM backend');
|
||||
}
|
||||
async embedKernel() {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'embedKernel not supported in WASM backend');
|
||||
}
|
||||
async extractKernel() {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'extractKernel not supported in WASM backend');
|
||||
}
|
||||
async embedEbpf() {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'embedEbpf not supported in WASM backend');
|
||||
}
|
||||
async extractEbpf() {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'extractEbpf not supported in WASM backend');
|
||||
}
|
||||
async segments() {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'segments not supported in WASM backend');
|
||||
}
|
||||
async dimension() {
|
||||
this.ensureHandle();
|
||||
const d = this.wasm.rvf_store_dimension(this.handle);
|
||||
if (d < 0)
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.StoreClosed);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
exports.WasmBackend = WasmBackend;
|
||||
// ---------------------------------------------------------------------------
|
||||
// Backend resolution
|
||||
// ---------------------------------------------------------------------------
|
||||
/**
|
||||
* Resolve a `BackendType` to a concrete `RvfBackend` instance.
|
||||
*
|
||||
* - `'node'` Always returns a `NodeBackend`.
|
||||
* - `'wasm'` Always returns a `WasmBackend`.
|
||||
* - `'auto'` Tries `node` first, falls back to `wasm`.
|
||||
*/
|
||||
function resolveBackend(type) {
|
||||
switch (type) {
|
||||
case 'node':
|
||||
return new NodeBackend();
|
||||
case 'wasm':
|
||||
return new WasmBackend();
|
||||
case 'auto': {
|
||||
// In Node.js environments, prefer native; in browsers, prefer WASM.
|
||||
const isNode = typeof process !== 'undefined' &&
|
||||
typeof process.versions !== 'undefined' &&
|
||||
typeof process.versions.node === 'string';
|
||||
return isNode ? new NodeBackend() : new WasmBackend();
|
||||
}
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
// Mapping helpers (TS options -> native/wasm shapes)
|
||||
// ---------------------------------------------------------------------------
|
||||
function mapMetricToNative(metric) {
|
||||
switch (metric) {
|
||||
case 'cosine':
|
||||
return 'Cosine';
|
||||
case 'dotproduct':
|
||||
return 'InnerProduct';
|
||||
case 'l2':
|
||||
default:
|
||||
return 'L2';
|
||||
}
|
||||
}
|
||||
function mapCompressionToNative(compression) {
|
||||
switch (compression) {
|
||||
case 'scalar':
|
||||
return 'Scalar';
|
||||
case 'product':
|
||||
return 'Product';
|
||||
case 'none':
|
||||
default:
|
||||
return 'None';
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function mapOptionsToNative(options) {
|
||||
return {
|
||||
dimension: options.dimensions,
|
||||
metric: mapMetricToNative(options.metric),
|
||||
profile: options.profile ?? 0,
|
||||
compression: mapCompressionToNative(options.compression),
|
||||
signing: options.signing ?? false,
|
||||
m: options.m ?? 16,
|
||||
ef_construction: options.efConstruction ?? 200,
|
||||
};
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function mapQueryOptionsToNative(options) {
|
||||
return {
|
||||
ef_search: options.efSearch ?? 100,
|
||||
// NAPI accepts the filter as a JSON string, not an object.
|
||||
filter: options.filter ? JSON.stringify(options.filter) : undefined,
|
||||
timeout_ms: options.timeoutMs ?? 0,
|
||||
};
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function mapNativeStatus(s) {
|
||||
return {
|
||||
totalVectors: s.total_vectors ?? s.totalVectors ?? 0,
|
||||
totalSegments: s.total_segments ?? s.totalSegments ?? 0,
|
||||
fileSizeBytes: s.file_size ?? s.fileSizeBytes ?? 0,
|
||||
epoch: s.current_epoch ?? s.epoch ?? 0,
|
||||
profileId: s.profile_id ?? s.profileId ?? 0,
|
||||
compactionState: mapCompactionState(s.compaction_state ?? s.compactionState),
|
||||
deadSpaceRatio: s.dead_space_ratio ?? s.deadSpaceRatio ?? 0,
|
||||
readOnly: s.read_only ?? s.readOnly ?? false,
|
||||
};
|
||||
}
|
||||
function mapCompactionState(state) {
|
||||
if (typeof state === 'string') {
|
||||
const lower = state.toLowerCase();
|
||||
if (lower === 'running')
|
||||
return 'running';
|
||||
if (lower === 'emergency')
|
||||
return 'emergency';
|
||||
}
|
||||
return 'idle';
|
||||
}
|
||||
//# sourceMappingURL=backend.js.map
|
||||
1
vendor/ruvector/npm/packages/rvf/src/backend.js.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/backend.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
790
vendor/ruvector/npm/packages/rvf/src/backend.ts
vendored
Normal file
790
vendor/ruvector/npm/packages/rvf/src/backend.ts
vendored
Normal file
@@ -0,0 +1,790 @@
|
||||
import type {
|
||||
RvfOptions,
|
||||
RvfQueryOptions,
|
||||
RvfSearchResult,
|
||||
RvfIngestResult,
|
||||
RvfIngestEntry,
|
||||
RvfDeleteResult,
|
||||
RvfCompactionResult,
|
||||
RvfStatus,
|
||||
RvfFilterExpr,
|
||||
RvfKernelData,
|
||||
RvfEbpfData,
|
||||
RvfSegmentInfo,
|
||||
BackendType,
|
||||
} from './types';
|
||||
import { RvfError, RvfErrorCode } from './errors';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Backend interface — every backend (node, wasm) must implement this.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Abstract backend that wraps either the native (N-API) or WASM build of
|
||||
* rvf-runtime. The `RvfDatabase` class delegates all I/O to a backend
|
||||
* instance, keeping the public API identical regardless of runtime.
|
||||
*/
|
||||
export interface RvfBackend {
|
||||
/** Create a new store file at `path` with the given options. */
|
||||
create(path: string, options: RvfOptions): Promise<void>;
|
||||
/** Open an existing store at `path` for read-write access. */
|
||||
open(path: string): Promise<void>;
|
||||
/** Open an existing store at `path` for read-only access. */
|
||||
openReadonly(path: string): Promise<void>;
|
||||
/** Ingest a batch of vectors. */
|
||||
ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult>;
|
||||
/** Query the k nearest neighbors. */
|
||||
query(vector: Float32Array, k: number, options?: RvfQueryOptions): Promise<RvfSearchResult[]>;
|
||||
/** Soft-delete vectors by ID. */
|
||||
delete(ids: string[]): Promise<RvfDeleteResult>;
|
||||
/** Soft-delete vectors matching a filter. */
|
||||
deleteByFilter(filter: RvfFilterExpr): Promise<RvfDeleteResult>;
|
||||
/** Run compaction to reclaim dead space. */
|
||||
compact(): Promise<RvfCompactionResult>;
|
||||
/** Get the current store status. */
|
||||
status(): Promise<RvfStatus>;
|
||||
/** Close the store, releasing locks. */
|
||||
close(): Promise<void>;
|
||||
// Lineage
|
||||
fileId(): Promise<string>;
|
||||
parentId(): Promise<string>;
|
||||
lineageDepth(): Promise<number>;
|
||||
derive(childPath: string, options?: RvfOptions): Promise<RvfBackend>;
|
||||
// Kernel / eBPF
|
||||
embedKernel(arch: number, kernelType: number, flags: number,
|
||||
image: Uint8Array, apiPort: number, cmdline?: string): Promise<number>;
|
||||
extractKernel(): Promise<RvfKernelData | null>;
|
||||
embedEbpf(programType: number, attachType: number, maxDimension: number,
|
||||
bytecode: Uint8Array, btf?: Uint8Array): Promise<number>;
|
||||
extractEbpf(): Promise<RvfEbpfData | null>;
|
||||
// Inspection
|
||||
segments(): Promise<RvfSegmentInfo[]>;
|
||||
dimension(): Promise<number>;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NodeBackend — wraps @ruvector/rvf-node (N-API)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Backend that delegates to the `@ruvector/rvf-node` native N-API addon.
|
||||
*
|
||||
* The native addon is loaded lazily on first use so that the SDK package can
|
||||
* be imported in environments where the native build is unavailable (e.g.
|
||||
* browsers) without throwing at import time.
|
||||
*/
|
||||
export class NodeBackend implements RvfBackend {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private native: any = null;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private handle: any = null;
|
||||
|
||||
// String ID <-> Numeric Label mappings (N-API layer requires i64 labels)
|
||||
private idToLabel: Map<string, number> = new Map();
|
||||
private labelToId: Map<number, string> = new Map();
|
||||
private nextLabel: number = 1; // RVF uses 1-based labels
|
||||
private storePath: string = '';
|
||||
|
||||
private async loadNative(): Promise<void> {
|
||||
if (this.native) return;
|
||||
try {
|
||||
// Dynamic import so the SDK can be bundled for browsers without
|
||||
// pulling in the native addon at compile time.
|
||||
// The NAPI addon exports a `RvfDatabase` class with factory methods.
|
||||
const mod = await import('@ruvector/rvf-node');
|
||||
this.native = mod.RvfDatabase ?? mod.default?.RvfDatabase ?? mod;
|
||||
} catch {
|
||||
throw new RvfError(
|
||||
RvfErrorCode.BackendNotFound,
|
||||
'Could not load @ruvector/rvf-node — is it installed?',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private ensureHandle(): void {
|
||||
if (!this.handle) {
|
||||
throw new RvfError(RvfErrorCode.StoreClosed);
|
||||
}
|
||||
}
|
||||
|
||||
async create(path: string, options: RvfOptions): Promise<void> {
|
||||
await this.loadNative();
|
||||
try {
|
||||
this.handle = await this.native.create(path, mapOptionsToNative(options));
|
||||
this.storePath = path;
|
||||
this.idToLabel.clear();
|
||||
this.labelToId.clear();
|
||||
this.nextLabel = 1;
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async open(path: string): Promise<void> {
|
||||
await this.loadNative();
|
||||
try {
|
||||
this.handle = await this.native.open(path);
|
||||
this.storePath = path;
|
||||
await this.loadMappings();
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async openReadonly(path: string): Promise<void> {
|
||||
await this.loadNative();
|
||||
try {
|
||||
this.handle = await this.native.openReadonly(path);
|
||||
this.storePath = path;
|
||||
await this.loadMappings();
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
// NAPI signature: ingestBatch(vectors: Float32Array, ids: i64[], metadata?)
|
||||
// Flatten individual vectors into a single contiguous Float32Array.
|
||||
const n = entries.length;
|
||||
if (n === 0) return { accepted: 0, rejected: 0, epoch: 0 };
|
||||
const first = entries[0].vector;
|
||||
const dim = first instanceof Float32Array ? first.length : first.length;
|
||||
const flat = new Float32Array(n * dim);
|
||||
for (let i = 0; i < n; i++) {
|
||||
const v = entries[i].vector;
|
||||
const f32 = v instanceof Float32Array ? v : new Float32Array(v);
|
||||
flat.set(f32, i * dim);
|
||||
}
|
||||
// Map string IDs to numeric labels for the N-API layer.
|
||||
// The native Rust HNSW expects i64 labels — non-numeric strings cause
|
||||
// silent data loss (NaN → dropped). We maintain a bidirectional
|
||||
// string↔label mapping and persist it as a sidecar JSON file.
|
||||
const ids = entries.map((e) => this.resolveLabel(e.id));
|
||||
const result = this.handle.ingestBatch(flat, ids);
|
||||
// Persist mappings after every ingest so they survive crashes.
|
||||
await this.saveMappings();
|
||||
return {
|
||||
accepted: Number(result.accepted),
|
||||
rejected: Number(result.rejected),
|
||||
epoch: result.epoch,
|
||||
};
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async query(
|
||||
vector: Float32Array,
|
||||
k: number,
|
||||
options?: RvfQueryOptions,
|
||||
): Promise<RvfSearchResult[]> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const nativeOpts = options ? mapQueryOptionsToNative(options) : undefined;
|
||||
const results = this.handle.query(vector, k, nativeOpts);
|
||||
// Map numeric labels back to original string IDs.
|
||||
return (results as Array<{ id: number; distance: number }>).map((r) => ({
|
||||
id: this.labelToId.get(Number(r.id)) ?? String(r.id),
|
||||
distance: r.distance,
|
||||
}));
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(ids: string[]): Promise<RvfDeleteResult> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
// Resolve string IDs to numeric labels for the N-API layer.
|
||||
const numIds = ids
|
||||
.map((id) => this.idToLabel.get(id))
|
||||
.filter((label): label is number => label !== undefined);
|
||||
if (numIds.length === 0) {
|
||||
return { deleted: 0, epoch: 0 };
|
||||
}
|
||||
const result = this.handle.delete(numIds);
|
||||
// Remove deleted entries from the mapping.
|
||||
for (const id of ids) {
|
||||
const label = this.idToLabel.get(id);
|
||||
if (label !== undefined) {
|
||||
this.idToLabel.delete(id);
|
||||
this.labelToId.delete(label);
|
||||
}
|
||||
}
|
||||
await this.saveMappings();
|
||||
return { deleted: Number(result.deleted), epoch: result.epoch };
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteByFilter(filter: RvfFilterExpr): Promise<RvfDeleteResult> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
// NAPI takes a JSON string for the filter expression.
|
||||
const result = this.handle.deleteByFilter(JSON.stringify(filter));
|
||||
return { deleted: Number(result.deleted), epoch: result.epoch };
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async compact(): Promise<RvfCompactionResult> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const result = this.handle.compact();
|
||||
return {
|
||||
segmentsCompacted: result.segmentsCompacted ?? result.segments_compacted,
|
||||
bytesReclaimed: Number(result.bytesReclaimed ?? result.bytes_reclaimed),
|
||||
epoch: result.epoch,
|
||||
};
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async status(): Promise<RvfStatus> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const s = this.handle.status();
|
||||
return mapNativeStatus(s);
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
if (!this.handle) return;
|
||||
try {
|
||||
await this.saveMappings();
|
||||
this.handle.close();
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
} finally {
|
||||
this.handle = null;
|
||||
this.idToLabel.clear();
|
||||
this.labelToId.clear();
|
||||
this.nextLabel = 1;
|
||||
this.storePath = '';
|
||||
}
|
||||
}
|
||||
|
||||
async fileId(): Promise<string> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.fileId();
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async parentId(): Promise<string> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.parentId();
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async lineageDepth(): Promise<number> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.lineageDepth();
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async derive(childPath: string, options?: RvfOptions): Promise<RvfBackend> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const nativeOpts = options ? mapOptionsToNative(options) : undefined;
|
||||
const childHandle = this.handle.derive(childPath, nativeOpts);
|
||||
const child = new NodeBackend();
|
||||
child.native = this.native;
|
||||
child.handle = childHandle;
|
||||
child.storePath = childPath;
|
||||
// Copy parent mappings to child (COW semantics)
|
||||
child.idToLabel = new Map(this.idToLabel);
|
||||
child.labelToId = new Map(this.labelToId);
|
||||
child.nextLabel = this.nextLabel;
|
||||
await child.saveMappings();
|
||||
return child;
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async embedKernel(
|
||||
arch: number, kernelType: number, flags: number,
|
||||
image: Uint8Array, apiPort: number, cmdline?: string
|
||||
): Promise<number> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.embedKernel(arch, kernelType, flags,
|
||||
Buffer.from(image), apiPort, cmdline);
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async extractKernel(): Promise<RvfKernelData | null> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const result = this.handle.extractKernel();
|
||||
if (!result) return null;
|
||||
return {
|
||||
header: new Uint8Array(result.header),
|
||||
image: new Uint8Array(result.image),
|
||||
};
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async embedEbpf(
|
||||
programType: number, attachType: number, maxDimension: number,
|
||||
bytecode: Uint8Array, btf?: Uint8Array
|
||||
): Promise<number> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.embedEbpf(programType, attachType, maxDimension,
|
||||
Buffer.from(bytecode), btf ? Buffer.from(btf) : undefined);
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async extractEbpf(): Promise<RvfEbpfData | null> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const result = this.handle.extractEbpf();
|
||||
if (!result) return null;
|
||||
return {
|
||||
header: new Uint8Array(result.header),
|
||||
payload: new Uint8Array(result.payload),
|
||||
};
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async segments(): Promise<RvfSegmentInfo[]> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const segs = this.handle.segments();
|
||||
return segs.map((s: any) => ({
|
||||
id: s.id,
|
||||
offset: s.offset,
|
||||
payloadLength: s.payloadLength ?? s.payload_length,
|
||||
segType: s.segType ?? s.seg_type,
|
||||
}));
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async dimension(): Promise<number> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
return this.handle.dimension();
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── String ID ↔ Numeric Label mapping helpers ───
|
||||
|
||||
/**
|
||||
* Get or allocate a numeric label for a string ID.
|
||||
* If the ID was already seen, returns the existing label.
|
||||
*/
|
||||
private resolveLabel(id: string): number {
|
||||
let label = this.idToLabel.get(id);
|
||||
if (label !== undefined) return label;
|
||||
label = this.nextLabel++;
|
||||
this.idToLabel.set(id, label);
|
||||
this.labelToId.set(label, id);
|
||||
return label;
|
||||
}
|
||||
|
||||
/** Path to the sidecar mappings file. */
|
||||
private mappingsPath(): string {
|
||||
return this.storePath ? this.storePath + '.idmap.json' : '';
|
||||
}
|
||||
|
||||
/** Persist the string↔label mapping to a sidecar JSON file. */
|
||||
private async saveMappings(): Promise<void> {
|
||||
const mp = this.mappingsPath();
|
||||
if (!mp) return;
|
||||
try {
|
||||
const fs = await import('fs');
|
||||
const data = JSON.stringify({
|
||||
idToLabel: Object.fromEntries(this.idToLabel),
|
||||
labelToId: Object.fromEntries(
|
||||
Array.from(this.labelToId.entries()).map(([k, v]) => [String(k), v]),
|
||||
),
|
||||
nextLabel: this.nextLabel,
|
||||
});
|
||||
fs.writeFileSync(mp, data, 'utf-8');
|
||||
} catch {
|
||||
// Non-fatal: mapping persistence is best-effort (e.g. read-only FS).
|
||||
}
|
||||
}
|
||||
|
||||
/** Load the string↔label mapping from the sidecar JSON file if it exists. */
|
||||
private async loadMappings(): Promise<void> {
|
||||
const mp = this.mappingsPath();
|
||||
if (!mp) return;
|
||||
try {
|
||||
const fs = await import('fs');
|
||||
if (!fs.existsSync(mp)) return;
|
||||
const raw = JSON.parse(fs.readFileSync(mp, 'utf-8'));
|
||||
this.idToLabel = new Map(Object.entries(raw.idToLabel ?? {}).map(
|
||||
([k, v]) => [k, Number(v)],
|
||||
));
|
||||
this.labelToId = new Map(
|
||||
Object.entries(raw.labelToId ?? {}).map(([k, v]) => [Number(k), v as string]),
|
||||
);
|
||||
this.nextLabel = raw.nextLabel ?? this.idToLabel.size + 1;
|
||||
} catch {
|
||||
// Non-fatal: start with empty mappings.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// WasmBackend — wraps @ruvector/rvf-wasm
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Backend that delegates to the `@ruvector/rvf-wasm` WASM build.
|
||||
*
|
||||
* The WASM microkernel exposes C-ABI store functions (`rvf_store_create`,
|
||||
* `rvf_store_query`, etc.) operating on integer handles. This backend wraps
|
||||
* them behind the same `RvfBackend` interface.
|
||||
*
|
||||
* Suitable for browser environments. The WASM module is loaded lazily.
|
||||
*/
|
||||
export class WasmBackend implements RvfBackend {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private wasm: any = null;
|
||||
/** Integer store handle returned by `rvf_store_create` / `rvf_store_open`. */
|
||||
private handle: number = 0;
|
||||
private dim: number = 0;
|
||||
|
||||
private async loadWasm(): Promise<void> {
|
||||
if (this.wasm) return;
|
||||
try {
|
||||
const mod = await import('@ruvector/rvf-wasm');
|
||||
// wasm-pack default export is the init function
|
||||
if (typeof mod.default === 'function') {
|
||||
this.wasm = await mod.default();
|
||||
} else {
|
||||
this.wasm = mod;
|
||||
}
|
||||
} catch {
|
||||
throw new RvfError(
|
||||
RvfErrorCode.BackendNotFound,
|
||||
'Could not load @ruvector/rvf-wasm — is it installed?',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private ensureHandle(): void {
|
||||
if (!this.handle) {
|
||||
throw new RvfError(RvfErrorCode.StoreClosed);
|
||||
}
|
||||
}
|
||||
|
||||
private metricCode(metric: string | undefined): number {
|
||||
switch (metric) {
|
||||
case 'Cosine': return 2;
|
||||
case 'InnerProduct': return 1;
|
||||
default: return 0; // L2
|
||||
}
|
||||
}
|
||||
|
||||
async create(_path: string, options: RvfOptions): Promise<void> {
|
||||
await this.loadWasm();
|
||||
try {
|
||||
const nativeOpts = mapOptionsToNative(options);
|
||||
const dim = nativeOpts.dimension as number;
|
||||
const metric = this.metricCode(nativeOpts.metric as string);
|
||||
const h = this.wasm.rvf_store_create(dim, metric);
|
||||
if (h <= 0) throw new Error('rvf_store_create returned ' + h);
|
||||
this.handle = h;
|
||||
this.dim = dim;
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async open(_path: string): Promise<void> {
|
||||
throw new RvfError(
|
||||
RvfErrorCode.BackendNotFound,
|
||||
'WASM backend does not support file-based open (in-memory only)',
|
||||
);
|
||||
}
|
||||
|
||||
async openReadonly(_path: string): Promise<void> {
|
||||
throw new RvfError(
|
||||
RvfErrorCode.BackendNotFound,
|
||||
'WASM backend does not support file-based openReadonly (in-memory only)',
|
||||
);
|
||||
}
|
||||
|
||||
async ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const n = entries.length;
|
||||
if (n === 0) return { accepted: 0, rejected: 0, epoch: 0 };
|
||||
const dim = this.dim || (entries[0].vector instanceof Float32Array
|
||||
? entries[0].vector.length : entries[0].vector.length);
|
||||
const flat = new Float32Array(n * dim);
|
||||
const ids = new BigUint64Array(n);
|
||||
for (let i = 0; i < n; i++) {
|
||||
const v = entries[i].vector;
|
||||
const f32 = v instanceof Float32Array ? v : new Float32Array(v);
|
||||
flat.set(f32, i * dim);
|
||||
ids[i] = BigInt(entries[i].id);
|
||||
}
|
||||
// Allocate in WASM memory and call
|
||||
const vecsPtr = this.wasm.rvf_alloc(flat.byteLength);
|
||||
const idsPtr = this.wasm.rvf_alloc(ids.byteLength);
|
||||
new Float32Array(this.wasm.memory.buffer, vecsPtr, flat.length).set(flat);
|
||||
new BigUint64Array(this.wasm.memory.buffer, idsPtr, ids.length).set(ids);
|
||||
const accepted = this.wasm.rvf_store_ingest(this.handle, vecsPtr, idsPtr, n);
|
||||
this.wasm.rvf_free(vecsPtr, flat.byteLength);
|
||||
this.wasm.rvf_free(idsPtr, ids.byteLength);
|
||||
return { accepted: accepted > 0 ? accepted : 0, rejected: accepted < 0 ? n : 0, epoch: 0 };
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async query(
|
||||
vector: Float32Array,
|
||||
k: number,
|
||||
_options?: RvfQueryOptions,
|
||||
): Promise<RvfSearchResult[]> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const queryPtr = this.wasm.rvf_alloc(vector.byteLength);
|
||||
new Float32Array(this.wasm.memory.buffer, queryPtr, vector.length).set(vector);
|
||||
// Each result = 8 bytes id + 4 bytes dist = 12 bytes
|
||||
const outSize = k * 12;
|
||||
const outPtr = this.wasm.rvf_alloc(outSize);
|
||||
const count = this.wasm.rvf_store_query(this.handle, queryPtr, k, 0, outPtr);
|
||||
const results: RvfSearchResult[] = [];
|
||||
const view = new DataView(this.wasm.memory.buffer);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const off = outPtr + i * 12;
|
||||
const id = view.getBigUint64(off, true);
|
||||
const dist = view.getFloat32(off + 8, true);
|
||||
results.push({ id: String(id), distance: dist });
|
||||
}
|
||||
this.wasm.rvf_free(queryPtr, vector.byteLength);
|
||||
this.wasm.rvf_free(outPtr, outSize);
|
||||
return results;
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(ids: string[]): Promise<RvfDeleteResult> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const arr = new BigUint64Array(ids.map((id) => BigInt(id)));
|
||||
const ptr = this.wasm.rvf_alloc(arr.byteLength);
|
||||
new BigUint64Array(this.wasm.memory.buffer, ptr, arr.length).set(arr);
|
||||
const deleted = this.wasm.rvf_store_delete(this.handle, ptr, ids.length);
|
||||
this.wasm.rvf_free(ptr, arr.byteLength);
|
||||
return { deleted: deleted > 0 ? deleted : 0, epoch: 0 };
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteByFilter(_filter: RvfFilterExpr): Promise<RvfDeleteResult> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'deleteByFilter not supported in WASM backend');
|
||||
}
|
||||
|
||||
async compact(): Promise<RvfCompactionResult> {
|
||||
return { segmentsCompacted: 0, bytesReclaimed: 0, epoch: 0 };
|
||||
}
|
||||
|
||||
async status(): Promise<RvfStatus> {
|
||||
this.ensureHandle();
|
||||
try {
|
||||
const outPtr = this.wasm.rvf_alloc(20);
|
||||
this.wasm.rvf_store_status(this.handle, outPtr);
|
||||
const view = new DataView(this.wasm.memory.buffer);
|
||||
const totalVectors = view.getUint32(outPtr, true);
|
||||
const dim = view.getUint32(outPtr + 4, true);
|
||||
this.wasm.rvf_free(outPtr, 20);
|
||||
return {
|
||||
totalVectors,
|
||||
totalSegments: 1,
|
||||
fileSizeBytes: 0,
|
||||
epoch: 0,
|
||||
profileId: 0,
|
||||
compactionState: 'idle',
|
||||
deadSpaceRatio: 0,
|
||||
readOnly: false,
|
||||
};
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
}
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
if (!this.handle) return;
|
||||
try {
|
||||
this.wasm.rvf_store_close(this.handle);
|
||||
} catch (err) {
|
||||
throw RvfError.fromNative(err);
|
||||
} finally {
|
||||
this.handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
async fileId(): Promise<string> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'fileId not supported in WASM backend');
|
||||
}
|
||||
async parentId(): Promise<string> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'parentId not supported in WASM backend');
|
||||
}
|
||||
async lineageDepth(): Promise<number> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'lineageDepth not supported in WASM backend');
|
||||
}
|
||||
async derive(_childPath: string, _options?: RvfOptions): Promise<RvfBackend> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'derive not supported in WASM backend');
|
||||
}
|
||||
async embedKernel(): Promise<number> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'embedKernel not supported in WASM backend');
|
||||
}
|
||||
async extractKernel(): Promise<RvfKernelData | null> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'extractKernel not supported in WASM backend');
|
||||
}
|
||||
async embedEbpf(): Promise<number> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'embedEbpf not supported in WASM backend');
|
||||
}
|
||||
async extractEbpf(): Promise<RvfEbpfData | null> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'extractEbpf not supported in WASM backend');
|
||||
}
|
||||
async segments(): Promise<RvfSegmentInfo[]> {
|
||||
throw new RvfError(RvfErrorCode.BackendNotFound, 'segments not supported in WASM backend');
|
||||
}
|
||||
async dimension(): Promise<number> {
|
||||
this.ensureHandle();
|
||||
const d = this.wasm.rvf_store_dimension(this.handle);
|
||||
if (d < 0) throw new RvfError(RvfErrorCode.StoreClosed);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Backend resolution
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Resolve a `BackendType` to a concrete `RvfBackend` instance.
|
||||
*
|
||||
* - `'node'` Always returns a `NodeBackend`.
|
||||
* - `'wasm'` Always returns a `WasmBackend`.
|
||||
* - `'auto'` Tries `node` first, falls back to `wasm`.
|
||||
*/
|
||||
export function resolveBackend(type: BackendType): RvfBackend {
|
||||
switch (type) {
|
||||
case 'node':
|
||||
return new NodeBackend();
|
||||
case 'wasm':
|
||||
return new WasmBackend();
|
||||
case 'auto': {
|
||||
// In Node.js environments, prefer native; in browsers, prefer WASM.
|
||||
const isNode =
|
||||
typeof process !== 'undefined' &&
|
||||
typeof process.versions !== 'undefined' &&
|
||||
typeof process.versions.node === 'string';
|
||||
return isNode ? new NodeBackend() : new WasmBackend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Mapping helpers (TS options -> native/wasm shapes)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function mapMetricToNative(metric: string | undefined): string {
|
||||
switch (metric) {
|
||||
case 'cosine':
|
||||
return 'Cosine';
|
||||
case 'dotproduct':
|
||||
return 'InnerProduct';
|
||||
case 'l2':
|
||||
default:
|
||||
return 'L2';
|
||||
}
|
||||
}
|
||||
|
||||
function mapCompressionToNative(compression: string | undefined): string {
|
||||
switch (compression) {
|
||||
case 'scalar':
|
||||
return 'Scalar';
|
||||
case 'product':
|
||||
return 'Product';
|
||||
case 'none':
|
||||
default:
|
||||
return 'None';
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function mapOptionsToNative(options: RvfOptions): Record<string, any> {
|
||||
return {
|
||||
dimension: options.dimensions,
|
||||
metric: mapMetricToNative(options.metric),
|
||||
profile: options.profile ?? 0,
|
||||
compression: mapCompressionToNative(options.compression),
|
||||
signing: options.signing ?? false,
|
||||
m: options.m ?? 16,
|
||||
ef_construction: options.efConstruction ?? 200,
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function mapQueryOptionsToNative(options: RvfQueryOptions): Record<string, any> {
|
||||
return {
|
||||
ef_search: options.efSearch ?? 100,
|
||||
// NAPI accepts the filter as a JSON string, not an object.
|
||||
filter: options.filter ? JSON.stringify(options.filter) : undefined,
|
||||
timeout_ms: options.timeoutMs ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function mapNativeStatus(s: any): RvfStatus {
|
||||
return {
|
||||
totalVectors: s.total_vectors ?? s.totalVectors ?? 0,
|
||||
totalSegments: s.total_segments ?? s.totalSegments ?? 0,
|
||||
fileSizeBytes: s.file_size ?? s.fileSizeBytes ?? 0,
|
||||
epoch: s.current_epoch ?? s.epoch ?? 0,
|
||||
profileId: s.profile_id ?? s.profileId ?? 0,
|
||||
compactionState: mapCompactionState(s.compaction_state ?? s.compactionState),
|
||||
deadSpaceRatio: s.dead_space_ratio ?? s.deadSpaceRatio ?? 0,
|
||||
readOnly: s.read_only ?? s.readOnly ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
function mapCompactionState(state: unknown): 'idle' | 'running' | 'emergency' {
|
||||
if (typeof state === 'string') {
|
||||
const lower = state.toLowerCase();
|
||||
if (lower === 'running') return 'running';
|
||||
if (lower === 'emergency') return 'emergency';
|
||||
}
|
||||
return 'idle';
|
||||
}
|
||||
119
vendor/ruvector/npm/packages/rvf/src/database.d.ts
vendored
Normal file
119
vendor/ruvector/npm/packages/rvf/src/database.d.ts
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
import type { RvfOptions, RvfQueryOptions, RvfSearchResult, RvfIngestResult, RvfIngestEntry, RvfDeleteResult, RvfCompactionResult, RvfStatus, RvfFilterExpr, RvfKernelData, RvfEbpfData, RvfSegmentInfo, BackendType } from './types';
|
||||
import type { RvfBackend } from './backend';
|
||||
/**
|
||||
* Main user-facing RVF database class.
|
||||
*
|
||||
* Wraps a backend implementation (`NodeBackend` or `WasmBackend`) and exposes
|
||||
* an ergonomic async API that mirrors the Rust `RvfStore` surface.
|
||||
*
|
||||
* Use the static factory methods (`create`, `open`, `openReadonly`) to obtain
|
||||
* an instance. Do not construct directly.
|
||||
*/
|
||||
export declare class RvfDatabase {
|
||||
private backend;
|
||||
private closed;
|
||||
private constructor();
|
||||
/**
|
||||
* Create a new RVF store at `path`.
|
||||
*
|
||||
* @param path File path for the new store.
|
||||
* @param options Store creation options (dimensions is required).
|
||||
* @param backend Backend to use. Default: `'auto'`.
|
||||
*/
|
||||
static create(path: string, options: RvfOptions, backend?: BackendType): Promise<RvfDatabase>;
|
||||
/**
|
||||
* Open an existing RVF store for read-write access.
|
||||
*
|
||||
* @param path File path to an existing `.rvf` file.
|
||||
* @param backend Backend to use. Default: `'auto'`.
|
||||
*/
|
||||
static open(path: string, backend?: BackendType): Promise<RvfDatabase>;
|
||||
/**
|
||||
* Open an existing RVF store for read-only access (no lock required).
|
||||
*
|
||||
* @param path File path to an existing `.rvf` file.
|
||||
* @param backend Backend to use. Default: `'auto'`.
|
||||
*/
|
||||
static openReadonly(path: string, backend?: BackendType): Promise<RvfDatabase>;
|
||||
/**
|
||||
* Create an RvfDatabase from an already-initialized backend.
|
||||
*
|
||||
* Used internally (e.g. by `derive()`) to wrap a child backend that was
|
||||
* created by the native layer without going through the normal open/create
|
||||
* flow.
|
||||
*/
|
||||
static fromBackend(backend: RvfBackend): RvfDatabase;
|
||||
/**
|
||||
* Ingest a batch of vectors into the store.
|
||||
*
|
||||
* @param entries Array of `{ id, vector, metadata? }` entries.
|
||||
* @returns Counts of accepted/rejected vectors and the new epoch.
|
||||
*/
|
||||
ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult>;
|
||||
/**
|
||||
* Soft-delete vectors by their IDs.
|
||||
*
|
||||
* @param ids Vector IDs to delete.
|
||||
*/
|
||||
delete(ids: string[]): Promise<RvfDeleteResult>;
|
||||
/**
|
||||
* Soft-delete all vectors matching a filter expression.
|
||||
*
|
||||
* @param filter The filter to match against vector metadata.
|
||||
*/
|
||||
deleteByFilter(filter: RvfFilterExpr): Promise<RvfDeleteResult>;
|
||||
/**
|
||||
* Query for the `k` nearest neighbors of a given vector.
|
||||
*
|
||||
* @param vector The query embedding.
|
||||
* @param k Number of results to return.
|
||||
* @param options Optional query parameters (efSearch, filter, timeout).
|
||||
* @returns Sorted search results (closest first).
|
||||
*/
|
||||
query(vector: Float32Array | number[], k: number, options?: RvfQueryOptions): Promise<RvfSearchResult[]>;
|
||||
/**
|
||||
* Run compaction to reclaim dead space from soft-deleted vectors.
|
||||
*/
|
||||
compact(): Promise<RvfCompactionResult>;
|
||||
/**
|
||||
* Get the current store status (vector count, file size, epoch, etc.).
|
||||
*/
|
||||
status(): Promise<RvfStatus>;
|
||||
/** Get this file's unique identifier as a hex string. */
|
||||
fileId(): Promise<string>;
|
||||
/** Get the parent file's identifier as a hex string (all zeros if root). */
|
||||
parentId(): Promise<string>;
|
||||
/** Get the lineage depth (0 for root files). */
|
||||
lineageDepth(): Promise<number>;
|
||||
/**
|
||||
* Derive a child store from this parent.
|
||||
*
|
||||
* Creates a new RVF file at `childPath` that records this store as its
|
||||
* parent for provenance tracking. Returns a new `RvfDatabase` wrapping
|
||||
* the child store.
|
||||
*/
|
||||
derive(childPath: string, options?: RvfOptions): Promise<RvfDatabase>;
|
||||
/** Embed a kernel image. Returns the segment ID. */
|
||||
embedKernel(arch: number, kernelType: number, flags: number, image: Uint8Array, apiPort: number, cmdline?: string): Promise<number>;
|
||||
/** Extract the kernel image. Returns null if not present. */
|
||||
extractKernel(): Promise<RvfKernelData | null>;
|
||||
/** Embed an eBPF program. Returns the segment ID. */
|
||||
embedEbpf(programType: number, attachType: number, maxDimension: number, bytecode: Uint8Array, btf?: Uint8Array): Promise<number>;
|
||||
/** Extract the eBPF program. Returns null if not present. */
|
||||
extractEbpf(): Promise<RvfEbpfData | null>;
|
||||
/** Get the list of segments in the store. */
|
||||
segments(): Promise<RvfSegmentInfo[]>;
|
||||
/** Get the vector dimensionality. */
|
||||
dimension(): Promise<number>;
|
||||
/**
|
||||
* Close the store, releasing the writer lock and flushing pending data.
|
||||
*
|
||||
* After calling `close()`, all other methods will throw `RvfError` with
|
||||
* code `StoreClosed`.
|
||||
*/
|
||||
close(): Promise<void>;
|
||||
/** True if the store has been closed. */
|
||||
get isClosed(): boolean;
|
||||
private ensureOpen;
|
||||
}
|
||||
//# sourceMappingURL=database.d.ts.map
|
||||
1
vendor/ruvector/npm/packages/rvf/src/database.d.ts.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/database.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["database.ts"],"names":[],"mappings":"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"}
|
||||
226
vendor/ruvector/npm/packages/rvf/src/database.js
vendored
Normal file
226
vendor/ruvector/npm/packages/rvf/src/database.js
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RvfDatabase = void 0;
|
||||
const backend_1 = require("./backend");
|
||||
const errors_1 = require("./errors");
|
||||
/**
|
||||
* Main user-facing RVF database class.
|
||||
*
|
||||
* Wraps a backend implementation (`NodeBackend` or `WasmBackend`) and exposes
|
||||
* an ergonomic async API that mirrors the Rust `RvfStore` surface.
|
||||
*
|
||||
* Use the static factory methods (`create`, `open`, `openReadonly`) to obtain
|
||||
* an instance. Do not construct directly.
|
||||
*/
|
||||
class RvfDatabase {
|
||||
constructor(backend) {
|
||||
this.closed = false;
|
||||
this.backend = backend;
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
// Factory methods
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Create a new RVF store at `path`.
|
||||
*
|
||||
* @param path File path for the new store.
|
||||
* @param options Store creation options (dimensions is required).
|
||||
* @param backend Backend to use. Default: `'auto'`.
|
||||
*/
|
||||
static async create(path, options, backend = 'auto') {
|
||||
const impl = (0, backend_1.resolveBackend)(backend);
|
||||
await impl.create(path, options);
|
||||
return new RvfDatabase(impl);
|
||||
}
|
||||
/**
|
||||
* Open an existing RVF store for read-write access.
|
||||
*
|
||||
* @param path File path to an existing `.rvf` file.
|
||||
* @param backend Backend to use. Default: `'auto'`.
|
||||
*/
|
||||
static async open(path, backend = 'auto') {
|
||||
const impl = (0, backend_1.resolveBackend)(backend);
|
||||
await impl.open(path);
|
||||
return new RvfDatabase(impl);
|
||||
}
|
||||
/**
|
||||
* Open an existing RVF store for read-only access (no lock required).
|
||||
*
|
||||
* @param path File path to an existing `.rvf` file.
|
||||
* @param backend Backend to use. Default: `'auto'`.
|
||||
*/
|
||||
static async openReadonly(path, backend = 'auto') {
|
||||
const impl = (0, backend_1.resolveBackend)(backend);
|
||||
await impl.openReadonly(path);
|
||||
return new RvfDatabase(impl);
|
||||
}
|
||||
/**
|
||||
* Create an RvfDatabase from an already-initialized backend.
|
||||
*
|
||||
* Used internally (e.g. by `derive()`) to wrap a child backend that was
|
||||
* created by the native layer without going through the normal open/create
|
||||
* flow.
|
||||
*/
|
||||
static fromBackend(backend) {
|
||||
return new RvfDatabase(backend);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
// Write operations
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Ingest a batch of vectors into the store.
|
||||
*
|
||||
* @param entries Array of `{ id, vector, metadata? }` entries.
|
||||
* @returns Counts of accepted/rejected vectors and the new epoch.
|
||||
*/
|
||||
async ingestBatch(entries) {
|
||||
this.ensureOpen();
|
||||
return this.backend.ingestBatch(entries);
|
||||
}
|
||||
/**
|
||||
* Soft-delete vectors by their IDs.
|
||||
*
|
||||
* @param ids Vector IDs to delete.
|
||||
*/
|
||||
async delete(ids) {
|
||||
this.ensureOpen();
|
||||
return this.backend.delete(ids);
|
||||
}
|
||||
/**
|
||||
* Soft-delete all vectors matching a filter expression.
|
||||
*
|
||||
* @param filter The filter to match against vector metadata.
|
||||
*/
|
||||
async deleteByFilter(filter) {
|
||||
this.ensureOpen();
|
||||
return this.backend.deleteByFilter(filter);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
// Read operations
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Query for the `k` nearest neighbors of a given vector.
|
||||
*
|
||||
* @param vector The query embedding.
|
||||
* @param k Number of results to return.
|
||||
* @param options Optional query parameters (efSearch, filter, timeout).
|
||||
* @returns Sorted search results (closest first).
|
||||
*/
|
||||
async query(vector, k, options) {
|
||||
this.ensureOpen();
|
||||
const f32 = vector instanceof Float32Array ? vector : new Float32Array(vector);
|
||||
return this.backend.query(f32, k, options);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
// Maintenance
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Run compaction to reclaim dead space from soft-deleted vectors.
|
||||
*/
|
||||
async compact() {
|
||||
this.ensureOpen();
|
||||
return this.backend.compact();
|
||||
}
|
||||
/**
|
||||
* Get the current store status (vector count, file size, epoch, etc.).
|
||||
*/
|
||||
async status() {
|
||||
this.ensureOpen();
|
||||
return this.backend.status();
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
// Lineage
|
||||
// -----------------------------------------------------------------------
|
||||
/** Get this file's unique identifier as a hex string. */
|
||||
async fileId() {
|
||||
this.ensureOpen();
|
||||
return this.backend.fileId();
|
||||
}
|
||||
/** Get the parent file's identifier as a hex string (all zeros if root). */
|
||||
async parentId() {
|
||||
this.ensureOpen();
|
||||
return this.backend.parentId();
|
||||
}
|
||||
/** Get the lineage depth (0 for root files). */
|
||||
async lineageDepth() {
|
||||
this.ensureOpen();
|
||||
return this.backend.lineageDepth();
|
||||
}
|
||||
/**
|
||||
* Derive a child store from this parent.
|
||||
*
|
||||
* Creates a new RVF file at `childPath` that records this store as its
|
||||
* parent for provenance tracking. Returns a new `RvfDatabase` wrapping
|
||||
* the child store.
|
||||
*/
|
||||
async derive(childPath, options) {
|
||||
this.ensureOpen();
|
||||
const childBackend = await this.backend.derive(childPath, options);
|
||||
return RvfDatabase.fromBackend(childBackend);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
// Kernel / eBPF
|
||||
// -----------------------------------------------------------------------
|
||||
/** Embed a kernel image. Returns the segment ID. */
|
||||
async embedKernel(arch, kernelType, flags, image, apiPort, cmdline) {
|
||||
this.ensureOpen();
|
||||
return this.backend.embedKernel(arch, kernelType, flags, image, apiPort, cmdline);
|
||||
}
|
||||
/** Extract the kernel image. Returns null if not present. */
|
||||
async extractKernel() {
|
||||
this.ensureOpen();
|
||||
return this.backend.extractKernel();
|
||||
}
|
||||
/** Embed an eBPF program. Returns the segment ID. */
|
||||
async embedEbpf(programType, attachType, maxDimension, bytecode, btf) {
|
||||
this.ensureOpen();
|
||||
return this.backend.embedEbpf(programType, attachType, maxDimension, bytecode, btf);
|
||||
}
|
||||
/** Extract the eBPF program. Returns null if not present. */
|
||||
async extractEbpf() {
|
||||
this.ensureOpen();
|
||||
return this.backend.extractEbpf();
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
// Inspection
|
||||
// -----------------------------------------------------------------------
|
||||
/** Get the list of segments in the store. */
|
||||
async segments() {
|
||||
this.ensureOpen();
|
||||
return this.backend.segments();
|
||||
}
|
||||
/** Get the vector dimensionality. */
|
||||
async dimension() {
|
||||
this.ensureOpen();
|
||||
return this.backend.dimension();
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
// Lifecycle
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Close the store, releasing the writer lock and flushing pending data.
|
||||
*
|
||||
* After calling `close()`, all other methods will throw `RvfError` with
|
||||
* code `StoreClosed`.
|
||||
*/
|
||||
async close() {
|
||||
if (this.closed)
|
||||
return;
|
||||
this.closed = true;
|
||||
await this.backend.close();
|
||||
}
|
||||
/** True if the store has been closed. */
|
||||
get isClosed() {
|
||||
return this.closed;
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
// Internal
|
||||
// -----------------------------------------------------------------------
|
||||
ensureOpen() {
|
||||
if (this.closed) {
|
||||
throw new errors_1.RvfError(errors_1.RvfErrorCode.StoreClosed);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.RvfDatabase = RvfDatabase;
|
||||
//# sourceMappingURL=database.js.map
|
||||
1
vendor/ruvector/npm/packages/rvf/src/database.js.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/database.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"database.js","sourceRoot":"","sources":["database.ts"],"names":[],"mappings":"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"}
|
||||
291
vendor/ruvector/npm/packages/rvf/src/database.ts
vendored
Normal file
291
vendor/ruvector/npm/packages/rvf/src/database.ts
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
import type {
|
||||
RvfOptions,
|
||||
RvfQueryOptions,
|
||||
RvfSearchResult,
|
||||
RvfIngestResult,
|
||||
RvfIngestEntry,
|
||||
RvfDeleteResult,
|
||||
RvfCompactionResult,
|
||||
RvfStatus,
|
||||
RvfFilterExpr,
|
||||
RvfKernelData,
|
||||
RvfEbpfData,
|
||||
RvfSegmentInfo,
|
||||
BackendType,
|
||||
} from './types';
|
||||
import type { RvfBackend } from './backend';
|
||||
import { resolveBackend } from './backend';
|
||||
import { RvfError, RvfErrorCode } from './errors';
|
||||
|
||||
/**
|
||||
* Main user-facing RVF database class.
|
||||
*
|
||||
* Wraps a backend implementation (`NodeBackend` or `WasmBackend`) and exposes
|
||||
* an ergonomic async API that mirrors the Rust `RvfStore` surface.
|
||||
*
|
||||
* Use the static factory methods (`create`, `open`, `openReadonly`) to obtain
|
||||
* an instance. Do not construct directly.
|
||||
*/
|
||||
export class RvfDatabase {
|
||||
private backend: RvfBackend;
|
||||
private closed = false;
|
||||
|
||||
private constructor(backend: RvfBackend) {
|
||||
this.backend = backend;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Factory methods
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a new RVF store at `path`.
|
||||
*
|
||||
* @param path File path for the new store.
|
||||
* @param options Store creation options (dimensions is required).
|
||||
* @param backend Backend to use. Default: `'auto'`.
|
||||
*/
|
||||
static async create(
|
||||
path: string,
|
||||
options: RvfOptions,
|
||||
backend: BackendType = 'auto',
|
||||
): Promise<RvfDatabase> {
|
||||
const impl = resolveBackend(backend);
|
||||
await impl.create(path, options);
|
||||
return new RvfDatabase(impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an existing RVF store for read-write access.
|
||||
*
|
||||
* @param path File path to an existing `.rvf` file.
|
||||
* @param backend Backend to use. Default: `'auto'`.
|
||||
*/
|
||||
static async open(
|
||||
path: string,
|
||||
backend: BackendType = 'auto',
|
||||
): Promise<RvfDatabase> {
|
||||
const impl = resolveBackend(backend);
|
||||
await impl.open(path);
|
||||
return new RvfDatabase(impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an existing RVF store for read-only access (no lock required).
|
||||
*
|
||||
* @param path File path to an existing `.rvf` file.
|
||||
* @param backend Backend to use. Default: `'auto'`.
|
||||
*/
|
||||
static async openReadonly(
|
||||
path: string,
|
||||
backend: BackendType = 'auto',
|
||||
): Promise<RvfDatabase> {
|
||||
const impl = resolveBackend(backend);
|
||||
await impl.openReadonly(path);
|
||||
return new RvfDatabase(impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an RvfDatabase from an already-initialized backend.
|
||||
*
|
||||
* Used internally (e.g. by `derive()`) to wrap a child backend that was
|
||||
* created by the native layer without going through the normal open/create
|
||||
* flow.
|
||||
*/
|
||||
static fromBackend(backend: RvfBackend): RvfDatabase {
|
||||
return new RvfDatabase(backend);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Write operations
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Ingest a batch of vectors into the store.
|
||||
*
|
||||
* @param entries Array of `{ id, vector, metadata? }` entries.
|
||||
* @returns Counts of accepted/rejected vectors and the new epoch.
|
||||
*/
|
||||
async ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult> {
|
||||
this.ensureOpen();
|
||||
return this.backend.ingestBatch(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-delete vectors by their IDs.
|
||||
*
|
||||
* @param ids Vector IDs to delete.
|
||||
*/
|
||||
async delete(ids: string[]): Promise<RvfDeleteResult> {
|
||||
this.ensureOpen();
|
||||
return this.backend.delete(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-delete all vectors matching a filter expression.
|
||||
*
|
||||
* @param filter The filter to match against vector metadata.
|
||||
*/
|
||||
async deleteByFilter(filter: RvfFilterExpr): Promise<RvfDeleteResult> {
|
||||
this.ensureOpen();
|
||||
return this.backend.deleteByFilter(filter);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Read operations
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Query for the `k` nearest neighbors of a given vector.
|
||||
*
|
||||
* @param vector The query embedding.
|
||||
* @param k Number of results to return.
|
||||
* @param options Optional query parameters (efSearch, filter, timeout).
|
||||
* @returns Sorted search results (closest first).
|
||||
*/
|
||||
async query(
|
||||
vector: Float32Array | number[],
|
||||
k: number,
|
||||
options?: RvfQueryOptions,
|
||||
): Promise<RvfSearchResult[]> {
|
||||
this.ensureOpen();
|
||||
const f32 = vector instanceof Float32Array ? vector : new Float32Array(vector);
|
||||
return this.backend.query(f32, k, options);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Maintenance
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Run compaction to reclaim dead space from soft-deleted vectors.
|
||||
*/
|
||||
async compact(): Promise<RvfCompactionResult> {
|
||||
this.ensureOpen();
|
||||
return this.backend.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current store status (vector count, file size, epoch, etc.).
|
||||
*/
|
||||
async status(): Promise<RvfStatus> {
|
||||
this.ensureOpen();
|
||||
return this.backend.status();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Lineage
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/** Get this file's unique identifier as a hex string. */
|
||||
async fileId(): Promise<string> {
|
||||
this.ensureOpen();
|
||||
return this.backend.fileId();
|
||||
}
|
||||
|
||||
/** Get the parent file's identifier as a hex string (all zeros if root). */
|
||||
async parentId(): Promise<string> {
|
||||
this.ensureOpen();
|
||||
return this.backend.parentId();
|
||||
}
|
||||
|
||||
/** Get the lineage depth (0 for root files). */
|
||||
async lineageDepth(): Promise<number> {
|
||||
this.ensureOpen();
|
||||
return this.backend.lineageDepth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive a child store from this parent.
|
||||
*
|
||||
* Creates a new RVF file at `childPath` that records this store as its
|
||||
* parent for provenance tracking. Returns a new `RvfDatabase` wrapping
|
||||
* the child store.
|
||||
*/
|
||||
async derive(childPath: string, options?: RvfOptions): Promise<RvfDatabase> {
|
||||
this.ensureOpen();
|
||||
const childBackend = await this.backend.derive(childPath, options);
|
||||
return RvfDatabase.fromBackend(childBackend);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Kernel / eBPF
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/** Embed a kernel image. Returns the segment ID. */
|
||||
async embedKernel(
|
||||
arch: number, kernelType: number, flags: number,
|
||||
image: Uint8Array, apiPort: number, cmdline?: string,
|
||||
): Promise<number> {
|
||||
this.ensureOpen();
|
||||
return this.backend.embedKernel(arch, kernelType, flags, image, apiPort, cmdline);
|
||||
}
|
||||
|
||||
/** Extract the kernel image. Returns null if not present. */
|
||||
async extractKernel(): Promise<RvfKernelData | null> {
|
||||
this.ensureOpen();
|
||||
return this.backend.extractKernel();
|
||||
}
|
||||
|
||||
/** Embed an eBPF program. Returns the segment ID. */
|
||||
async embedEbpf(
|
||||
programType: number, attachType: number, maxDimension: number,
|
||||
bytecode: Uint8Array, btf?: Uint8Array,
|
||||
): Promise<number> {
|
||||
this.ensureOpen();
|
||||
return this.backend.embedEbpf(programType, attachType, maxDimension, bytecode, btf);
|
||||
}
|
||||
|
||||
/** Extract the eBPF program. Returns null if not present. */
|
||||
async extractEbpf(): Promise<RvfEbpfData | null> {
|
||||
this.ensureOpen();
|
||||
return this.backend.extractEbpf();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Inspection
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/** Get the list of segments in the store. */
|
||||
async segments(): Promise<RvfSegmentInfo[]> {
|
||||
this.ensureOpen();
|
||||
return this.backend.segments();
|
||||
}
|
||||
|
||||
/** Get the vector dimensionality. */
|
||||
async dimension(): Promise<number> {
|
||||
this.ensureOpen();
|
||||
return this.backend.dimension();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Lifecycle
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Close the store, releasing the writer lock and flushing pending data.
|
||||
*
|
||||
* After calling `close()`, all other methods will throw `RvfError` with
|
||||
* code `StoreClosed`.
|
||||
*/
|
||||
async close(): Promise<void> {
|
||||
if (this.closed) return;
|
||||
this.closed = true;
|
||||
await this.backend.close();
|
||||
}
|
||||
|
||||
/** True if the store has been closed. */
|
||||
get isClosed(): boolean {
|
||||
return this.closed;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Internal
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
private ensureOpen(): void {
|
||||
if (this.closed) {
|
||||
throw new RvfError(RvfErrorCode.StoreClosed);
|
||||
}
|
||||
}
|
||||
}
|
||||
63
vendor/ruvector/npm/packages/rvf/src/errors.d.ts
vendored
Normal file
63
vendor/ruvector/npm/packages/rvf/src/errors.d.ts
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Error codes mirroring the Rust `ErrorCode` enum (rvf-types).
|
||||
*
|
||||
* The high byte is the category, the low byte is the specific error.
|
||||
*/
|
||||
export declare enum RvfErrorCode {
|
||||
Ok = 0,
|
||||
OkPartial = 1,
|
||||
InvalidMagic = 256,
|
||||
InvalidVersion = 257,
|
||||
InvalidChecksum = 258,
|
||||
InvalidSignature = 259,
|
||||
TruncatedSegment = 260,
|
||||
InvalidManifest = 261,
|
||||
ManifestNotFound = 262,
|
||||
UnknownSegmentType = 263,
|
||||
AlignmentError = 264,
|
||||
DimensionMismatch = 512,
|
||||
EmptyIndex = 513,
|
||||
MetricUnsupported = 514,
|
||||
FilterParseError = 515,
|
||||
KTooLarge = 516,
|
||||
Timeout = 517,
|
||||
LockHeld = 768,
|
||||
LockStale = 769,
|
||||
DiskFull = 770,
|
||||
FsyncFailed = 771,
|
||||
SegmentTooLarge = 772,
|
||||
ReadOnly = 773,
|
||||
TileTrap = 1024,
|
||||
TileOom = 1025,
|
||||
TileTimeout = 1026,
|
||||
TileInvalidMsg = 1027,
|
||||
TileUnsupportedOp = 1028,
|
||||
KeyNotFound = 1280,
|
||||
KeyExpired = 1281,
|
||||
DecryptFailed = 1282,
|
||||
AlgoUnsupported = 1283,
|
||||
BackendNotFound = 65280,
|
||||
BackendInitFailed = 65281,
|
||||
StoreClosed = 65282
|
||||
}
|
||||
/**
|
||||
* Custom error class for all RVF operations.
|
||||
*
|
||||
* Carries a typed `code` field for programmatic matching and a
|
||||
* human-readable `message`.
|
||||
*/
|
||||
export declare class RvfError extends Error {
|
||||
/** The RVF error code. */
|
||||
readonly code: RvfErrorCode;
|
||||
/** Error category (high byte of the code). */
|
||||
get category(): number;
|
||||
/** True when the category indicates a format-level (fatal) error. */
|
||||
get isFormatError(): boolean;
|
||||
constructor(code: RvfErrorCode, detail?: string);
|
||||
/**
|
||||
* Create an RvfError from a native binding error.
|
||||
* Attempts to extract an error code from the message or object.
|
||||
*/
|
||||
static fromNative(err: unknown): RvfError;
|
||||
}
|
||||
//# sourceMappingURL=errors.d.ts.map
|
||||
1
vendor/ruvector/npm/packages/rvf/src/errors.d.ts.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/errors.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,oBAAY,YAAY;IAEtB,EAAE,IAAS;IACX,SAAS,IAAS;IAGlB,YAAY,MAAS;IACrB,cAAc,MAAS;IACvB,eAAe,MAAS;IACxB,gBAAgB,MAAS;IACzB,gBAAgB,MAAS;IACzB,eAAe,MAAS;IACxB,gBAAgB,MAAS;IACzB,kBAAkB,MAAS;IAC3B,cAAc,MAAS;IAGvB,iBAAiB,MAAS;IAC1B,UAAU,MAAS;IACnB,iBAAiB,MAAS;IAC1B,gBAAgB,MAAS;IACzB,SAAS,MAAS;IAClB,OAAO,MAAS;IAGhB,QAAQ,MAAS;IACjB,SAAS,MAAS;IAClB,QAAQ,MAAS;IACjB,WAAW,MAAS;IACpB,eAAe,MAAS;IACxB,QAAQ,MAAS;IAGjB,QAAQ,OAAS;IACjB,OAAO,OAAS;IAChB,WAAW,OAAS;IACpB,cAAc,OAAS;IACvB,iBAAiB,OAAS;IAG1B,WAAW,OAAS;IACpB,UAAU,OAAS;IACnB,aAAa,OAAS;IACtB,eAAe,OAAS;IAGxB,eAAe,QAAS;IACxB,iBAAiB,QAAS;IAC1B,WAAW,QAAS;CACrB;AAyCD;;;;;GAKG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAE5B,8CAA8C;IAC9C,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,qEAAqE;IACrE,IAAI,aAAa,IAAI,OAAO,CAE3B;gBAEW,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM;IAQ/C;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;CAc1C"}
|
||||
135
vendor/ruvector/npm/packages/rvf/src/errors.js
vendored
Normal file
135
vendor/ruvector/npm/packages/rvf/src/errors.js
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RvfError = exports.RvfErrorCode = void 0;
|
||||
/**
|
||||
* Error codes mirroring the Rust `ErrorCode` enum (rvf-types).
|
||||
*
|
||||
* The high byte is the category, the low byte is the specific error.
|
||||
*/
|
||||
var RvfErrorCode;
|
||||
(function (RvfErrorCode) {
|
||||
// Category 0x00: Success
|
||||
RvfErrorCode[RvfErrorCode["Ok"] = 0] = "Ok";
|
||||
RvfErrorCode[RvfErrorCode["OkPartial"] = 1] = "OkPartial";
|
||||
// Category 0x01: Format Errors
|
||||
RvfErrorCode[RvfErrorCode["InvalidMagic"] = 256] = "InvalidMagic";
|
||||
RvfErrorCode[RvfErrorCode["InvalidVersion"] = 257] = "InvalidVersion";
|
||||
RvfErrorCode[RvfErrorCode["InvalidChecksum"] = 258] = "InvalidChecksum";
|
||||
RvfErrorCode[RvfErrorCode["InvalidSignature"] = 259] = "InvalidSignature";
|
||||
RvfErrorCode[RvfErrorCode["TruncatedSegment"] = 260] = "TruncatedSegment";
|
||||
RvfErrorCode[RvfErrorCode["InvalidManifest"] = 261] = "InvalidManifest";
|
||||
RvfErrorCode[RvfErrorCode["ManifestNotFound"] = 262] = "ManifestNotFound";
|
||||
RvfErrorCode[RvfErrorCode["UnknownSegmentType"] = 263] = "UnknownSegmentType";
|
||||
RvfErrorCode[RvfErrorCode["AlignmentError"] = 264] = "AlignmentError";
|
||||
// Category 0x02: Query Errors
|
||||
RvfErrorCode[RvfErrorCode["DimensionMismatch"] = 512] = "DimensionMismatch";
|
||||
RvfErrorCode[RvfErrorCode["EmptyIndex"] = 513] = "EmptyIndex";
|
||||
RvfErrorCode[RvfErrorCode["MetricUnsupported"] = 514] = "MetricUnsupported";
|
||||
RvfErrorCode[RvfErrorCode["FilterParseError"] = 515] = "FilterParseError";
|
||||
RvfErrorCode[RvfErrorCode["KTooLarge"] = 516] = "KTooLarge";
|
||||
RvfErrorCode[RvfErrorCode["Timeout"] = 517] = "Timeout";
|
||||
// Category 0x03: Write Errors
|
||||
RvfErrorCode[RvfErrorCode["LockHeld"] = 768] = "LockHeld";
|
||||
RvfErrorCode[RvfErrorCode["LockStale"] = 769] = "LockStale";
|
||||
RvfErrorCode[RvfErrorCode["DiskFull"] = 770] = "DiskFull";
|
||||
RvfErrorCode[RvfErrorCode["FsyncFailed"] = 771] = "FsyncFailed";
|
||||
RvfErrorCode[RvfErrorCode["SegmentTooLarge"] = 772] = "SegmentTooLarge";
|
||||
RvfErrorCode[RvfErrorCode["ReadOnly"] = 773] = "ReadOnly";
|
||||
// Category 0x04: Tile Errors (WASM Microkernel)
|
||||
RvfErrorCode[RvfErrorCode["TileTrap"] = 1024] = "TileTrap";
|
||||
RvfErrorCode[RvfErrorCode["TileOom"] = 1025] = "TileOom";
|
||||
RvfErrorCode[RvfErrorCode["TileTimeout"] = 1026] = "TileTimeout";
|
||||
RvfErrorCode[RvfErrorCode["TileInvalidMsg"] = 1027] = "TileInvalidMsg";
|
||||
RvfErrorCode[RvfErrorCode["TileUnsupportedOp"] = 1028] = "TileUnsupportedOp";
|
||||
// Category 0x05: Crypto Errors
|
||||
RvfErrorCode[RvfErrorCode["KeyNotFound"] = 1280] = "KeyNotFound";
|
||||
RvfErrorCode[RvfErrorCode["KeyExpired"] = 1281] = "KeyExpired";
|
||||
RvfErrorCode[RvfErrorCode["DecryptFailed"] = 1282] = "DecryptFailed";
|
||||
RvfErrorCode[RvfErrorCode["AlgoUnsupported"] = 1283] = "AlgoUnsupported";
|
||||
// SDK-level errors (0xFF__)
|
||||
RvfErrorCode[RvfErrorCode["BackendNotFound"] = 65280] = "BackendNotFound";
|
||||
RvfErrorCode[RvfErrorCode["BackendInitFailed"] = 65281] = "BackendInitFailed";
|
||||
RvfErrorCode[RvfErrorCode["StoreClosed"] = 65282] = "StoreClosed";
|
||||
})(RvfErrorCode || (exports.RvfErrorCode = RvfErrorCode = {}));
|
||||
/** Human-readable labels for each error code. */
|
||||
const ERROR_MESSAGES = {
|
||||
[RvfErrorCode.Ok]: 'Operation succeeded',
|
||||
[RvfErrorCode.OkPartial]: 'Partial success (some items failed)',
|
||||
[RvfErrorCode.InvalidMagic]: 'Segment magic mismatch',
|
||||
[RvfErrorCode.InvalidVersion]: 'Unsupported segment version',
|
||||
[RvfErrorCode.InvalidChecksum]: 'Segment hash verification failed',
|
||||
[RvfErrorCode.InvalidSignature]: 'Cryptographic signature invalid',
|
||||
[RvfErrorCode.TruncatedSegment]: 'Segment payload shorter than declared',
|
||||
[RvfErrorCode.InvalidManifest]: 'Root manifest validation failed',
|
||||
[RvfErrorCode.ManifestNotFound]: 'No valid manifest in file',
|
||||
[RvfErrorCode.UnknownSegmentType]: 'Unrecognized segment type',
|
||||
[RvfErrorCode.AlignmentError]: 'Data not at expected 64-byte boundary',
|
||||
[RvfErrorCode.DimensionMismatch]: 'Query vector dimension != index dimension',
|
||||
[RvfErrorCode.EmptyIndex]: 'No index segments available',
|
||||
[RvfErrorCode.MetricUnsupported]: 'Requested distance metric not available',
|
||||
[RvfErrorCode.FilterParseError]: 'Invalid filter expression',
|
||||
[RvfErrorCode.KTooLarge]: 'Requested K exceeds available vectors',
|
||||
[RvfErrorCode.Timeout]: 'Query exceeded time budget',
|
||||
[RvfErrorCode.LockHeld]: 'Another writer holds the lock',
|
||||
[RvfErrorCode.LockStale]: 'Lock file exists but owner is dead',
|
||||
[RvfErrorCode.DiskFull]: 'Insufficient space for write',
|
||||
[RvfErrorCode.FsyncFailed]: 'Durable write (fsync) failed',
|
||||
[RvfErrorCode.SegmentTooLarge]: 'Segment exceeds 4 GB limit',
|
||||
[RvfErrorCode.ReadOnly]: 'Store opened in read-only mode',
|
||||
[RvfErrorCode.TileTrap]: 'WASM trap (OOB, unreachable, stack overflow)',
|
||||
[RvfErrorCode.TileOom]: 'Tile exceeded scratch memory',
|
||||
[RvfErrorCode.TileTimeout]: 'Tile computation exceeded time budget',
|
||||
[RvfErrorCode.TileInvalidMsg]: 'Malformed hub-tile message',
|
||||
[RvfErrorCode.TileUnsupportedOp]: 'Operation not available on this profile',
|
||||
[RvfErrorCode.KeyNotFound]: 'Referenced key_id not found',
|
||||
[RvfErrorCode.KeyExpired]: 'Key past valid_until timestamp',
|
||||
[RvfErrorCode.DecryptFailed]: 'Decryption or auth tag verification failed',
|
||||
[RvfErrorCode.AlgoUnsupported]: 'Cryptographic algorithm not implemented',
|
||||
[RvfErrorCode.BackendNotFound]: 'No suitable backend found (install @ruvector/rvf-node or @ruvector/rvf-wasm)',
|
||||
[RvfErrorCode.BackendInitFailed]: 'Backend initialization failed',
|
||||
[RvfErrorCode.StoreClosed]: 'Store has been closed',
|
||||
};
|
||||
/**
|
||||
* Custom error class for all RVF operations.
|
||||
*
|
||||
* Carries a typed `code` field for programmatic matching and a
|
||||
* human-readable `message`.
|
||||
*/
|
||||
class RvfError extends Error {
|
||||
/** Error category (high byte of the code). */
|
||||
get category() {
|
||||
return (this.code >> 8) & 0xff;
|
||||
}
|
||||
/** True when the category indicates a format-level (fatal) error. */
|
||||
get isFormatError() {
|
||||
return this.category === 0x01;
|
||||
}
|
||||
constructor(code, detail) {
|
||||
const base = ERROR_MESSAGES[code] ?? `RVF error 0x${code.toString(16).padStart(4, '0')}`;
|
||||
const message = detail ? `${base}: ${detail}` : base;
|
||||
super(message);
|
||||
this.name = 'RvfError';
|
||||
this.code = code;
|
||||
}
|
||||
/**
|
||||
* Create an RvfError from a native binding error.
|
||||
* Attempts to extract an error code from the message or object.
|
||||
*/
|
||||
static fromNative(err) {
|
||||
if (err instanceof RvfError)
|
||||
return err;
|
||||
if (err instanceof Error) {
|
||||
const codeMatch = err.message.match(/0x([0-9a-fA-F]{4})/);
|
||||
if (codeMatch) {
|
||||
const code = parseInt(codeMatch[1], 16);
|
||||
if (code in RvfErrorCode) {
|
||||
return new RvfError(code, err.message);
|
||||
}
|
||||
}
|
||||
return new RvfError(RvfErrorCode.BackendInitFailed, err.message);
|
||||
}
|
||||
return new RvfError(RvfErrorCode.BackendInitFailed, String(err));
|
||||
}
|
||||
}
|
||||
exports.RvfError = RvfError;
|
||||
//# sourceMappingURL=errors.js.map
|
||||
1
vendor/ruvector/npm/packages/rvf/src/errors.js.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/errors.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"errors.js","sourceRoot":"","sources":["errors.ts"],"names":[],"mappings":"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"}
|
||||
142
vendor/ruvector/npm/packages/rvf/src/errors.ts
vendored
Normal file
142
vendor/ruvector/npm/packages/rvf/src/errors.ts
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* Error codes mirroring the Rust `ErrorCode` enum (rvf-types).
|
||||
*
|
||||
* The high byte is the category, the low byte is the specific error.
|
||||
*/
|
||||
export enum RvfErrorCode {
|
||||
// Category 0x00: Success
|
||||
Ok = 0x0000,
|
||||
OkPartial = 0x0001,
|
||||
|
||||
// Category 0x01: Format Errors
|
||||
InvalidMagic = 0x0100,
|
||||
InvalidVersion = 0x0101,
|
||||
InvalidChecksum = 0x0102,
|
||||
InvalidSignature = 0x0103,
|
||||
TruncatedSegment = 0x0104,
|
||||
InvalidManifest = 0x0105,
|
||||
ManifestNotFound = 0x0106,
|
||||
UnknownSegmentType = 0x0107,
|
||||
AlignmentError = 0x0108,
|
||||
|
||||
// Category 0x02: Query Errors
|
||||
DimensionMismatch = 0x0200,
|
||||
EmptyIndex = 0x0201,
|
||||
MetricUnsupported = 0x0202,
|
||||
FilterParseError = 0x0203,
|
||||
KTooLarge = 0x0204,
|
||||
Timeout = 0x0205,
|
||||
|
||||
// Category 0x03: Write Errors
|
||||
LockHeld = 0x0300,
|
||||
LockStale = 0x0301,
|
||||
DiskFull = 0x0302,
|
||||
FsyncFailed = 0x0303,
|
||||
SegmentTooLarge = 0x0304,
|
||||
ReadOnly = 0x0305,
|
||||
|
||||
// Category 0x04: Tile Errors (WASM Microkernel)
|
||||
TileTrap = 0x0400,
|
||||
TileOom = 0x0401,
|
||||
TileTimeout = 0x0402,
|
||||
TileInvalidMsg = 0x0403,
|
||||
TileUnsupportedOp = 0x0404,
|
||||
|
||||
// Category 0x05: Crypto Errors
|
||||
KeyNotFound = 0x0500,
|
||||
KeyExpired = 0x0501,
|
||||
DecryptFailed = 0x0502,
|
||||
AlgoUnsupported = 0x0503,
|
||||
|
||||
// SDK-level errors (0xFF__)
|
||||
BackendNotFound = 0xff00,
|
||||
BackendInitFailed = 0xff01,
|
||||
StoreClosed = 0xff02,
|
||||
}
|
||||
|
||||
/** Human-readable labels for each error code. */
|
||||
const ERROR_MESSAGES: Record<number, string> = {
|
||||
[RvfErrorCode.Ok]: 'Operation succeeded',
|
||||
[RvfErrorCode.OkPartial]: 'Partial success (some items failed)',
|
||||
[RvfErrorCode.InvalidMagic]: 'Segment magic mismatch',
|
||||
[RvfErrorCode.InvalidVersion]: 'Unsupported segment version',
|
||||
[RvfErrorCode.InvalidChecksum]: 'Segment hash verification failed',
|
||||
[RvfErrorCode.InvalidSignature]: 'Cryptographic signature invalid',
|
||||
[RvfErrorCode.TruncatedSegment]: 'Segment payload shorter than declared',
|
||||
[RvfErrorCode.InvalidManifest]: 'Root manifest validation failed',
|
||||
[RvfErrorCode.ManifestNotFound]: 'No valid manifest in file',
|
||||
[RvfErrorCode.UnknownSegmentType]: 'Unrecognized segment type',
|
||||
[RvfErrorCode.AlignmentError]: 'Data not at expected 64-byte boundary',
|
||||
[RvfErrorCode.DimensionMismatch]: 'Query vector dimension != index dimension',
|
||||
[RvfErrorCode.EmptyIndex]: 'No index segments available',
|
||||
[RvfErrorCode.MetricUnsupported]: 'Requested distance metric not available',
|
||||
[RvfErrorCode.FilterParseError]: 'Invalid filter expression',
|
||||
[RvfErrorCode.KTooLarge]: 'Requested K exceeds available vectors',
|
||||
[RvfErrorCode.Timeout]: 'Query exceeded time budget',
|
||||
[RvfErrorCode.LockHeld]: 'Another writer holds the lock',
|
||||
[RvfErrorCode.LockStale]: 'Lock file exists but owner is dead',
|
||||
[RvfErrorCode.DiskFull]: 'Insufficient space for write',
|
||||
[RvfErrorCode.FsyncFailed]: 'Durable write (fsync) failed',
|
||||
[RvfErrorCode.SegmentTooLarge]: 'Segment exceeds 4 GB limit',
|
||||
[RvfErrorCode.ReadOnly]: 'Store opened in read-only mode',
|
||||
[RvfErrorCode.TileTrap]: 'WASM trap (OOB, unreachable, stack overflow)',
|
||||
[RvfErrorCode.TileOom]: 'Tile exceeded scratch memory',
|
||||
[RvfErrorCode.TileTimeout]: 'Tile computation exceeded time budget',
|
||||
[RvfErrorCode.TileInvalidMsg]: 'Malformed hub-tile message',
|
||||
[RvfErrorCode.TileUnsupportedOp]: 'Operation not available on this profile',
|
||||
[RvfErrorCode.KeyNotFound]: 'Referenced key_id not found',
|
||||
[RvfErrorCode.KeyExpired]: 'Key past valid_until timestamp',
|
||||
[RvfErrorCode.DecryptFailed]: 'Decryption or auth tag verification failed',
|
||||
[RvfErrorCode.AlgoUnsupported]: 'Cryptographic algorithm not implemented',
|
||||
[RvfErrorCode.BackendNotFound]: 'No suitable backend found (install @ruvector/rvf-node or @ruvector/rvf-wasm)',
|
||||
[RvfErrorCode.BackendInitFailed]: 'Backend initialization failed',
|
||||
[RvfErrorCode.StoreClosed]: 'Store has been closed',
|
||||
};
|
||||
|
||||
/**
|
||||
* Custom error class for all RVF operations.
|
||||
*
|
||||
* Carries a typed `code` field for programmatic matching and a
|
||||
* human-readable `message`.
|
||||
*/
|
||||
export class RvfError extends Error {
|
||||
/** The RVF error code. */
|
||||
readonly code: RvfErrorCode;
|
||||
|
||||
/** Error category (high byte of the code). */
|
||||
get category(): number {
|
||||
return (this.code >> 8) & 0xff;
|
||||
}
|
||||
|
||||
/** True when the category indicates a format-level (fatal) error. */
|
||||
get isFormatError(): boolean {
|
||||
return this.category === 0x01;
|
||||
}
|
||||
|
||||
constructor(code: RvfErrorCode, detail?: string) {
|
||||
const base = ERROR_MESSAGES[code] ?? `RVF error 0x${code.toString(16).padStart(4, '0')}`;
|
||||
const message = detail ? `${base}: ${detail}` : base;
|
||||
super(message);
|
||||
this.name = 'RvfError';
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an RvfError from a native binding error.
|
||||
* Attempts to extract an error code from the message or object.
|
||||
*/
|
||||
static fromNative(err: unknown): RvfError {
|
||||
if (err instanceof RvfError) return err;
|
||||
if (err instanceof Error) {
|
||||
const codeMatch = err.message.match(/0x([0-9a-fA-F]{4})/);
|
||||
if (codeMatch) {
|
||||
const code = parseInt(codeMatch[1], 16);
|
||||
if (code in RvfErrorCode) {
|
||||
return new RvfError(code as RvfErrorCode, err.message);
|
||||
}
|
||||
}
|
||||
return new RvfError(RvfErrorCode.BackendInitFailed, err.message);
|
||||
}
|
||||
return new RvfError(RvfErrorCode.BackendInitFailed, String(err));
|
||||
}
|
||||
}
|
||||
33
vendor/ruvector/npm/packages/rvf/src/externals.d.ts
vendored
Normal file
33
vendor/ruvector/npm/packages/rvf/src/externals.d.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Ambient module declarations for optional native/WASM backends.
|
||||
*
|
||||
* These let the SDK compile without the actual native packages installed.
|
||||
* At runtime the dynamic `import()` calls in backend.ts will resolve to the
|
||||
* real implementations (or throw, which is handled gracefully).
|
||||
*/
|
||||
|
||||
declare module '@ruvector/rvf-node' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const RvfDatabase: any;
|
||||
}
|
||||
|
||||
declare module '@ruvector/rvf-wasm' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const init: (...args: any[]) => Promise<any>;
|
||||
export default init;
|
||||
}
|
||||
|
||||
declare module '@ruvector/rvf-solver' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const RvfSolver: any;
|
||||
export type TrainOptions = any;
|
||||
export type TrainResult = any;
|
||||
export type AcceptanceOptions = any;
|
||||
export type AcceptanceManifest = any;
|
||||
export type AcceptanceModeResult = any;
|
||||
export type CycleMetrics = any;
|
||||
export type PolicyState = any;
|
||||
export type SkipMode = any;
|
||||
export type SkipModeStats = any;
|
||||
export type CompiledConfig = any;
|
||||
}
|
||||
1
vendor/ruvector/npm/packages/rvf/src/index.d.ts.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/index.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,cAAc,EACd,aAAa,EACb,WAAW,EACX,cAAc,EACd,WAAW,EACX,aAAa,EACb,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGlD,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGrE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,YAAY,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,aAAa,EACb,cAAc,GACf,MAAM,sBAAsB,CAAC"}
|
||||
1
vendor/ruvector/npm/packages/rvf/src/index.js.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/index.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AA2BH,wBAAwB;AACxB,mCAAkD;AAAzC,kGAAA,QAAQ,OAAA;AAAE,sGAAA,YAAY,OAAA;AAI/B,qCAAqE;AAA5D,sGAAA,WAAW,OAAA;AAAE,sGAAA,WAAW,OAAA;AAAE,yGAAA,cAAc,OAAA;AAEjD,oCAAoC;AACpC,uCAAyC;AAAhC,uGAAA,WAAW,OAAA;AAEpB,oCAAoC;AACpC,mDAAiD;AAAxC,uGAAA,SAAS,OAAA"}
|
||||
68
vendor/ruvector/npm/packages/rvf/src/index.ts
vendored
Normal file
68
vendor/ruvector/npm/packages/rvf/src/index.ts
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @ruvector/rvf — Unified TypeScript SDK for the RuVector Format.
|
||||
*
|
||||
* Works with both the native Node.js backend (`@ruvector/rvf-node`) and
|
||||
* the browser WASM backend (`@ruvector/rvf-wasm`).
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { RvfDatabase } from '@ruvector/rvf';
|
||||
*
|
||||
* const db = await RvfDatabase.create('./my.rvf', { dimensions: 128 });
|
||||
* await db.ingestBatch([
|
||||
* { id: '1', vector: new Float32Array(128) },
|
||||
* ]);
|
||||
* const results = await db.query(new Float32Array(128), 10);
|
||||
* await db.close();
|
||||
* ```
|
||||
*/
|
||||
|
||||
// Re-export all public types
|
||||
export type {
|
||||
DistanceMetric,
|
||||
CompressionProfile,
|
||||
HardwareProfile,
|
||||
RvfOptions,
|
||||
RvfFilterValue,
|
||||
RvfFilterExpr,
|
||||
RvfQueryOptions,
|
||||
RvfSearchResult,
|
||||
RvfIngestResult,
|
||||
RvfIngestEntry,
|
||||
RvfDeleteResult,
|
||||
RvfCompactionResult,
|
||||
CompactionState,
|
||||
RvfStatus,
|
||||
DerivationType,
|
||||
RvfKernelData,
|
||||
RvfEbpfData,
|
||||
RvfSegmentInfo,
|
||||
BackendType,
|
||||
RvfIndexStats,
|
||||
RvfWitnessResult,
|
||||
} from './types';
|
||||
|
||||
// Re-export error types
|
||||
export { RvfError, RvfErrorCode } from './errors';
|
||||
|
||||
// Re-export backend interface and implementations
|
||||
export type { RvfBackend } from './backend';
|
||||
export { NodeBackend, WasmBackend, resolveBackend } from './backend';
|
||||
|
||||
// Re-export the main database class
|
||||
export { RvfDatabase } from './database';
|
||||
|
||||
// Re-export solver (AGI components)
|
||||
export { RvfSolver } from '@ruvector/rvf-solver';
|
||||
export type {
|
||||
TrainOptions,
|
||||
TrainResult,
|
||||
AcceptanceOptions,
|
||||
AcceptanceManifest,
|
||||
AcceptanceModeResult,
|
||||
CycleMetrics,
|
||||
PolicyState,
|
||||
SkipMode,
|
||||
SkipModeStats,
|
||||
CompiledConfig,
|
||||
} from '@ruvector/rvf-solver';
|
||||
213
vendor/ruvector/npm/packages/rvf/src/types.d.ts
vendored
Normal file
213
vendor/ruvector/npm/packages/rvf/src/types.d.ts
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* Distance metric for vector similarity search.
|
||||
*
|
||||
* - `l2` Squared Euclidean distance.
|
||||
* - `cosine` Cosine distance (1 - cosine_similarity).
|
||||
* - `dotproduct` Negated inner (dot) product.
|
||||
*/
|
||||
export type DistanceMetric = 'l2' | 'cosine' | 'dotproduct';
|
||||
/**
|
||||
* Compression profile for stored vectors.
|
||||
*
|
||||
* - `none` Raw fp32 vectors.
|
||||
* - `scalar` Scalar quantization (int8).
|
||||
* - `product` Product quantization.
|
||||
*/
|
||||
export type CompressionProfile = 'none' | 'scalar' | 'product';
|
||||
/**
|
||||
* Hardware profile selector.
|
||||
*
|
||||
* 0 = Generic, 1 = Core, 2 = Hot, 3 = Full.
|
||||
*/
|
||||
export type HardwareProfile = 0 | 1 | 2 | 3;
|
||||
/** Options for creating a new RVF store. */
|
||||
export interface RvfOptions {
|
||||
/** Vector dimensionality (required, must be > 0). */
|
||||
dimensions: number;
|
||||
/** Distance metric for similarity search. Default: `'l2'`. */
|
||||
metric?: DistanceMetric;
|
||||
/** Hardware profile identifier. Default: `0` (Generic). */
|
||||
profile?: HardwareProfile;
|
||||
/** Compression profile. Default: `'none'`. */
|
||||
compression?: CompressionProfile;
|
||||
/** Enable segment signing. Default: `false`. */
|
||||
signing?: boolean;
|
||||
/** HNSW M parameter: max edges per node per layer. Default: `16`. */
|
||||
m?: number;
|
||||
/** HNSW ef_construction: beam width during index build. Default: `200`. */
|
||||
efConstruction?: number;
|
||||
}
|
||||
/** Primitive value types usable in filter expressions. */
|
||||
export type RvfFilterValue = number | string | boolean;
|
||||
/**
|
||||
* A filter expression for metadata-based vector filtering.
|
||||
*
|
||||
* Leaf operators compare a `fieldId` against a literal `value`.
|
||||
* Composite operators combine sub-expressions with boolean logic.
|
||||
*/
|
||||
export type RvfFilterExpr = {
|
||||
op: 'eq';
|
||||
fieldId: number;
|
||||
value: RvfFilterValue;
|
||||
} | {
|
||||
op: 'ne';
|
||||
fieldId: number;
|
||||
value: RvfFilterValue;
|
||||
} | {
|
||||
op: 'lt';
|
||||
fieldId: number;
|
||||
value: RvfFilterValue;
|
||||
} | {
|
||||
op: 'le';
|
||||
fieldId: number;
|
||||
value: RvfFilterValue;
|
||||
} | {
|
||||
op: 'gt';
|
||||
fieldId: number;
|
||||
value: RvfFilterValue;
|
||||
} | {
|
||||
op: 'ge';
|
||||
fieldId: number;
|
||||
value: RvfFilterValue;
|
||||
} | {
|
||||
op: 'in';
|
||||
fieldId: number;
|
||||
values: RvfFilterValue[];
|
||||
} | {
|
||||
op: 'range';
|
||||
fieldId: number;
|
||||
low: RvfFilterValue;
|
||||
high: RvfFilterValue;
|
||||
} | {
|
||||
op: 'and';
|
||||
exprs: RvfFilterExpr[];
|
||||
} | {
|
||||
op: 'or';
|
||||
exprs: RvfFilterExpr[];
|
||||
} | {
|
||||
op: 'not';
|
||||
expr: RvfFilterExpr;
|
||||
};
|
||||
/** Options controlling a query operation. */
|
||||
export interface RvfQueryOptions {
|
||||
/** HNSW ef_search parameter (beam width during search). Default: `100`. */
|
||||
efSearch?: number;
|
||||
/** Optional metadata filter expression. */
|
||||
filter?: RvfFilterExpr;
|
||||
/** Query timeout in milliseconds (0 = no timeout). Default: `0`. */
|
||||
timeoutMs?: number;
|
||||
}
|
||||
/** A single search result: vector ID and distance. */
|
||||
export interface RvfSearchResult {
|
||||
/** The vector's unique identifier (string-encoded u64). */
|
||||
id: string;
|
||||
/** Distance from the query vector (lower = more similar). */
|
||||
distance: number;
|
||||
}
|
||||
/** Result of a batch ingest operation. */
|
||||
export interface RvfIngestResult {
|
||||
/** Number of vectors successfully ingested. */
|
||||
accepted: number;
|
||||
/** Number of vectors rejected. */
|
||||
rejected: number;
|
||||
/** Manifest epoch after the ingest commit. */
|
||||
epoch: number;
|
||||
}
|
||||
/** Result of a delete operation. */
|
||||
export interface RvfDeleteResult {
|
||||
/** Number of vectors soft-deleted. */
|
||||
deleted: number;
|
||||
/** Manifest epoch after the delete commit. */
|
||||
epoch: number;
|
||||
}
|
||||
/** Result of a compaction operation. */
|
||||
export interface RvfCompactionResult {
|
||||
/** Number of segments compacted. */
|
||||
segmentsCompacted: number;
|
||||
/** Bytes of dead space reclaimed. */
|
||||
bytesReclaimed: number;
|
||||
/** Manifest epoch after compaction commit. */
|
||||
epoch: number;
|
||||
}
|
||||
/** Compaction state as reported in store status. */
|
||||
export type CompactionState = 'idle' | 'running' | 'emergency';
|
||||
/** A snapshot of the store's current state. */
|
||||
export interface RvfStatus {
|
||||
/** Total number of live (non-deleted) vectors. */
|
||||
totalVectors: number;
|
||||
/** Total number of segments in the file. */
|
||||
totalSegments: number;
|
||||
/** Total file size in bytes. */
|
||||
fileSizeBytes: number;
|
||||
/** Current manifest epoch. */
|
||||
epoch: number;
|
||||
/** Hardware profile identifier. */
|
||||
profileId: number;
|
||||
/** Current compaction state. */
|
||||
compactionState: CompactionState;
|
||||
/** Ratio of dead space to total (0.0 - 1.0). */
|
||||
deadSpaceRatio: number;
|
||||
/** Whether the store is open in read-only mode. */
|
||||
readOnly: boolean;
|
||||
}
|
||||
/** A single entry for batch ingestion. */
|
||||
export interface RvfIngestEntry {
|
||||
/** Unique vector identifier. */
|
||||
id: string;
|
||||
/** The embedding vector (must match store dimensions). */
|
||||
vector: Float32Array | number[];
|
||||
/** Optional per-vector metadata fields. */
|
||||
metadata?: Record<string, RvfFilterValue>;
|
||||
}
|
||||
/** Derivation type for creating derived stores. */
|
||||
export type DerivationType = 'filter' | 'merge' | 'snapshot' | 'transform';
|
||||
/** Data returned from kernel extraction. */
|
||||
export interface RvfKernelData {
|
||||
/** Serialized KernelHeader bytes. */
|
||||
header: Uint8Array;
|
||||
/** Raw kernel image bytes. */
|
||||
image: Uint8Array;
|
||||
}
|
||||
/** Data returned from eBPF extraction. */
|
||||
export interface RvfEbpfData {
|
||||
/** Serialized EbpfHeader bytes. */
|
||||
header: Uint8Array;
|
||||
/** Program bytecode + optional BTF. */
|
||||
payload: Uint8Array;
|
||||
}
|
||||
/** Information about a segment in the store. */
|
||||
export interface RvfSegmentInfo {
|
||||
/** Segment ID. */
|
||||
id: number;
|
||||
/** File offset of the segment. */
|
||||
offset: number;
|
||||
/** Payload length in bytes. */
|
||||
payloadLength: number;
|
||||
/** Segment type name (e.g. "vec", "manifest", "kernel"). */
|
||||
segType: string;
|
||||
}
|
||||
/** Identifies which backend implementation to use. */
|
||||
export type BackendType = 'node' | 'wasm' | 'auto';
|
||||
/** HNSW index statistics. */
|
||||
export interface RvfIndexStats {
|
||||
/** Number of indexed vectors. */
|
||||
indexedVectors: number;
|
||||
/** Number of HNSW layers. */
|
||||
layers: number;
|
||||
/** M parameter (max edges per node per layer). */
|
||||
m: number;
|
||||
/** ef_construction parameter. */
|
||||
efConstruction: number;
|
||||
/** Whether the index needs rebuilding. */
|
||||
needsRebuild: boolean;
|
||||
}
|
||||
/** Result of witness chain verification. */
|
||||
export interface RvfWitnessResult {
|
||||
/** Whether the chain is valid. */
|
||||
valid: boolean;
|
||||
/** Number of entries in the chain. */
|
||||
entries: number;
|
||||
/** Error message if invalid. */
|
||||
error?: string;
|
||||
}
|
||||
//# sourceMappingURL=types.d.ts.map
|
||||
1
vendor/ruvector/npm/packages/rvf/src/types.d.ts.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/types.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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"}
|
||||
3
vendor/ruvector/npm/packages/rvf/src/types.js
vendored
Normal file
3
vendor/ruvector/npm/packages/rvf/src/types.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=types.js.map
|
||||
1
vendor/ruvector/npm/packages/rvf/src/types.js.map
vendored
Normal file
1
vendor/ruvector/npm/packages/rvf/src/types.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":""}
|
||||
237
vendor/ruvector/npm/packages/rvf/src/types.ts
vendored
Normal file
237
vendor/ruvector/npm/packages/rvf/src/types.ts
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* Distance metric for vector similarity search.
|
||||
*
|
||||
* - `l2` Squared Euclidean distance.
|
||||
* - `cosine` Cosine distance (1 - cosine_similarity).
|
||||
* - `dotproduct` Negated inner (dot) product.
|
||||
*/
|
||||
export type DistanceMetric = 'l2' | 'cosine' | 'dotproduct';
|
||||
|
||||
/**
|
||||
* Compression profile for stored vectors.
|
||||
*
|
||||
* - `none` Raw fp32 vectors.
|
||||
* - `scalar` Scalar quantization (int8).
|
||||
* - `product` Product quantization.
|
||||
*/
|
||||
export type CompressionProfile = 'none' | 'scalar' | 'product';
|
||||
|
||||
/**
|
||||
* Hardware profile selector.
|
||||
*
|
||||
* 0 = Generic, 1 = Core, 2 = Hot, 3 = Full.
|
||||
*/
|
||||
export type HardwareProfile = 0 | 1 | 2 | 3;
|
||||
|
||||
/** Options for creating a new RVF store. */
|
||||
export interface RvfOptions {
|
||||
/** Vector dimensionality (required, must be > 0). */
|
||||
dimensions: number;
|
||||
/** Distance metric for similarity search. Default: `'l2'`. */
|
||||
metric?: DistanceMetric;
|
||||
/** Hardware profile identifier. Default: `0` (Generic). */
|
||||
profile?: HardwareProfile;
|
||||
/** Compression profile. Default: `'none'`. */
|
||||
compression?: CompressionProfile;
|
||||
/** Enable segment signing. Default: `false`. */
|
||||
signing?: boolean;
|
||||
/** HNSW M parameter: max edges per node per layer. Default: `16`. */
|
||||
m?: number;
|
||||
/** HNSW ef_construction: beam width during index build. Default: `200`. */
|
||||
efConstruction?: number;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Filter expressions
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Primitive value types usable in filter expressions. */
|
||||
export type RvfFilterValue = number | string | boolean;
|
||||
|
||||
/**
|
||||
* A filter expression for metadata-based vector filtering.
|
||||
*
|
||||
* Leaf operators compare a `fieldId` against a literal `value`.
|
||||
* Composite operators combine sub-expressions with boolean logic.
|
||||
*/
|
||||
export type RvfFilterExpr =
|
||||
| { op: 'eq'; fieldId: number; value: RvfFilterValue }
|
||||
| { op: 'ne'; fieldId: number; value: RvfFilterValue }
|
||||
| { op: 'lt'; fieldId: number; value: RvfFilterValue }
|
||||
| { op: 'le'; fieldId: number; value: RvfFilterValue }
|
||||
| { op: 'gt'; fieldId: number; value: RvfFilterValue }
|
||||
| { op: 'ge'; fieldId: number; value: RvfFilterValue }
|
||||
| { op: 'in'; fieldId: number; values: RvfFilterValue[] }
|
||||
| { op: 'range'; fieldId: number; low: RvfFilterValue; high: RvfFilterValue }
|
||||
| { op: 'and'; exprs: RvfFilterExpr[] }
|
||||
| { op: 'or'; exprs: RvfFilterExpr[] }
|
||||
| { op: 'not'; expr: RvfFilterExpr };
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Query options
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Options controlling a query operation. */
|
||||
export interface RvfQueryOptions {
|
||||
/** HNSW ef_search parameter (beam width during search). Default: `100`. */
|
||||
efSearch?: number;
|
||||
/** Optional metadata filter expression. */
|
||||
filter?: RvfFilterExpr;
|
||||
/** Query timeout in milliseconds (0 = no timeout). Default: `0`. */
|
||||
timeoutMs?: number;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Result types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** A single search result: vector ID and distance. */
|
||||
export interface RvfSearchResult {
|
||||
/** The vector's unique identifier (string-encoded u64). */
|
||||
id: string;
|
||||
/** Distance from the query vector (lower = more similar). */
|
||||
distance: number;
|
||||
}
|
||||
|
||||
/** Result of a batch ingest operation. */
|
||||
export interface RvfIngestResult {
|
||||
/** Number of vectors successfully ingested. */
|
||||
accepted: number;
|
||||
/** Number of vectors rejected. */
|
||||
rejected: number;
|
||||
/** Manifest epoch after the ingest commit. */
|
||||
epoch: number;
|
||||
}
|
||||
|
||||
/** Result of a delete operation. */
|
||||
export interface RvfDeleteResult {
|
||||
/** Number of vectors soft-deleted. */
|
||||
deleted: number;
|
||||
/** Manifest epoch after the delete commit. */
|
||||
epoch: number;
|
||||
}
|
||||
|
||||
/** Result of a compaction operation. */
|
||||
export interface RvfCompactionResult {
|
||||
/** Number of segments compacted. */
|
||||
segmentsCompacted: number;
|
||||
/** Bytes of dead space reclaimed. */
|
||||
bytesReclaimed: number;
|
||||
/** Manifest epoch after compaction commit. */
|
||||
epoch: number;
|
||||
}
|
||||
|
||||
/** Compaction state as reported in store status. */
|
||||
export type CompactionState = 'idle' | 'running' | 'emergency';
|
||||
|
||||
/** A snapshot of the store's current state. */
|
||||
export interface RvfStatus {
|
||||
/** Total number of live (non-deleted) vectors. */
|
||||
totalVectors: number;
|
||||
/** Total number of segments in the file. */
|
||||
totalSegments: number;
|
||||
/** Total file size in bytes. */
|
||||
fileSizeBytes: number;
|
||||
/** Current manifest epoch. */
|
||||
epoch: number;
|
||||
/** Hardware profile identifier. */
|
||||
profileId: number;
|
||||
/** Current compaction state. */
|
||||
compactionState: CompactionState;
|
||||
/** Ratio of dead space to total (0.0 - 1.0). */
|
||||
deadSpaceRatio: number;
|
||||
/** Whether the store is open in read-only mode. */
|
||||
readOnly: boolean;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Ingest entry
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** A single entry for batch ingestion. */
|
||||
export interface RvfIngestEntry {
|
||||
/** Unique vector identifier. */
|
||||
id: string;
|
||||
/** The embedding vector (must match store dimensions). */
|
||||
vector: Float32Array | number[];
|
||||
/** Optional per-vector metadata fields. */
|
||||
metadata?: Record<string, RvfFilterValue>;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Lineage types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Derivation type for creating derived stores. */
|
||||
export type DerivationType = 'filter' | 'merge' | 'snapshot' | 'transform';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Kernel / eBPF types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Data returned from kernel extraction. */
|
||||
export interface RvfKernelData {
|
||||
/** Serialized KernelHeader bytes. */
|
||||
header: Uint8Array;
|
||||
/** Raw kernel image bytes. */
|
||||
image: Uint8Array;
|
||||
}
|
||||
|
||||
/** Data returned from eBPF extraction. */
|
||||
export interface RvfEbpfData {
|
||||
/** Serialized EbpfHeader bytes. */
|
||||
header: Uint8Array;
|
||||
/** Program bytecode + optional BTF. */
|
||||
payload: Uint8Array;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Segment inspection
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Information about a segment in the store. */
|
||||
export interface RvfSegmentInfo {
|
||||
/** Segment ID. */
|
||||
id: number;
|
||||
/** File offset of the segment. */
|
||||
offset: number;
|
||||
/** Payload length in bytes. */
|
||||
payloadLength: number;
|
||||
/** Segment type name (e.g. "vec", "manifest", "kernel"). */
|
||||
segType: string;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Backend identifier
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Identifies which backend implementation to use. */
|
||||
export type BackendType = 'node' | 'wasm' | 'auto';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Solver / AGI types (re-exported from @ruvector/rvf-solver)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** HNSW index statistics. */
|
||||
export interface RvfIndexStats {
|
||||
/** Number of indexed vectors. */
|
||||
indexedVectors: number;
|
||||
/** Number of HNSW layers. */
|
||||
layers: number;
|
||||
/** M parameter (max edges per node per layer). */
|
||||
m: number;
|
||||
/** ef_construction parameter. */
|
||||
efConstruction: number;
|
||||
/** Whether the index needs rebuilding. */
|
||||
needsRebuild: boolean;
|
||||
}
|
||||
|
||||
/** Result of witness chain verification. */
|
||||
export interface RvfWitnessResult {
|
||||
/** Whether the chain is valid. */
|
||||
valid: boolean;
|
||||
/** Number of entries in the chain. */
|
||||
entries: number;
|
||||
/** Error message if invalid. */
|
||||
error?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user