Spaces:
Running
API Reference
Exports
// Classes
import { AgentMemory, VromCache } from 'vrom.js';
// Types (type-only imports)
import type {
AgentMemoryOptions,
MountOptions,
MountStatus,
SearchOptions,
SearchResult,
FormatContextOptions,
ChunkMetadata,
DownloadProgress,
StorageEstimate,
VromRegistry,
VromRegistryEntry,
VromManifest,
} from 'vrom.js';
Class: AgentMemory
The primary SDK class. Wraps the WASM HNSW engine, a background ONNX embedding worker, and an OPFS-backed vROM cache into a single, ergonomic interface.
Constructor
new AgentMemory(options?: AgentMemoryOptions)
| Option | Type | Default | Description |
|---|---|---|---|
workerPath |
string |
Auto-resolved via import.meta.url |
URL to the embed worker JS file. Override when the auto-resolved path is incorrect (e.g., CDN usage). |
wasmPkgPath |
string |
Auto-resolved via import.meta.url |
URL to the WASM JS bindings module (vecdb_wasm.js). |
registryUrl |
string |
HF Hub CDN | URL to a custom vROM registry JSON. Default points to philipp-zettl/vrom-registry on HF Hub. |
logLevel |
'silent' | 'error' | 'warn' | 'info' | 'debug' |
'warn' |
Console log verbosity. 'info' is useful during development; 'debug' logs every download progress event. |
Example:
// Defaults β works in most bundler setups
const memory = new AgentMemory();
// Explicit paths for CDN or non-bundler setups
const memory = new AgentMemory({
workerPath: '/static/embed-worker.js',
wasmPkgPath: '/static/wasm-pkg/vecdb_wasm.js',
logLevel: 'info',
});
init()
async init(): Promise<void>
Initialize the WASM engine and spawn the background embedding worker. Must be called once before any other method.
Calling init() multiple times is safe β subsequent calls are no-ops.
What it does:
- Dynamically imports the WASM JS bindings module
- Initializes the WASM binary (
wasm_bindgen init) - Creates a Web Worker from
workerPathwithtype: 'module' - Sets up the internal message handler for the worker protocol
Throws:
- If the WASM module fails to load (invalid path, network error)
- If the Worker fails to spawn (CSP violation, invalid path)
Example:
const memory = new AgentMemory();
await memory.init();
// Now ready to mount vROMs
mount(vromIdOrUri, options?)
async mount(vromIdOrUri: string, options?: MountOptions): Promise<MountStatus>
Mount a vROM knowledge base. This is the main loading method that handles the full pipeline: registry lookup β OPFS cache β CDN download β WASM index load β embedding model diffing.
Parameters:
| Param | Type | Description |
|---|---|---|
vromIdOrUri |
string |
A vROM identifier. Can be a bare ID ('hf-transformers-docs') or a hub:// URI ('hub://hf-transformers-docs'). |
options |
MountOptions |
Optional configuration (see below). |
MountOptions:
| Option | Type | Default | Description |
|---|---|---|---|
onProgress |
(p: DownloadProgress) => void |
β | Callback fired during vROM download. Receives phase ('manifest', 'index', 'done'), file, loaded, and total bytes. |
forceDownload |
boolean |
false |
Skip the OPFS cache and re-download from CDN. Useful for forcing updates. |
Returns: Promise<MountStatus> β the current state after mounting.
Mount lifecycle:
- Registry resolve β looks up the vROM ID in the registry to get CDN URLs, required model, and metadata.
- OPFS cache check β if the vROM is already cached locally, skips the download.
- CDN download (if cache miss) β streams the HNSW index JSON with progress reporting. The manifest and index are written to OPFS.
- WASM load β reads the index JSON from OPFS and calls
VectorDB.load()to deserialize the HNSW graph into the WASM engine. Frees any previously loaded graph. - Model diffing β compares the required embedding model (from the vROM manifest) with the currently loaded model. If different, loads the new model in the background worker. If the same, skips reload entirely (hot-swap).
Throws:
'Call init() first'β ifinit()hasn't been called'vROM \'...\' not found in registry'β if the ID doesn't exist in the registry'Failed to read index for \'...\''β if OPFS read fails after download- Network errors during CDN download
- Model load errors from the worker
Example:
// Simple mount
const status = await memory.mount('hf-transformers-docs');
console.log(`${status.vectors} vectors, model: ${status.model}`);
// With progress tracking
await memory.mount('hf-ml-training', {
onProgress: ({ phase, loaded, total }) => {
if (phase === 'index' && total > 0) {
console.log(`Download: ${(loaded / total * 100).toFixed(0)}%`);
}
},
forceDownload: false,
});
// Hot-swap β if the new vROM uses the same embedding model, the model stays loaded
await memory.mount('hf-transformers-docs');
await memory.mount('hf-ml-training'); // Model already loaded β instant swap
unmount()
unmount(): void
Unmount the current vROM. Frees the HNSW graph from WASM memory but keeps the OPFS cache (so re-mounting is instant). The embedding model stays loaded in the worker.
After unmounting, search() will throw until a new vROM is mounted.
search(query, options?)
async search(query: string, options?: SearchOptions): Promise<SearchResult[]>
Search the mounted vROM with a natural language query.
Parameters:
| Param | Type | Description |
|---|---|---|
query |
string |
Natural language search query. Gets embedded by the background worker before searching. |
options |
SearchOptions |
Optional search configuration (see below). |
SearchOptions:
| Option | Type | Default | Description |
|---|---|---|---|
topK |
number |
5 |
Number of results to return. |
expandContext |
boolean |
false |
If true, follows prev_chunk_id/next_chunk_id linked-list pointers to expand each result with surrounding chunks. |
contextWindow |
number |
1 |
Number of chunks to expand in each direction (before and after). Only used when expandContext is true. |
efSearch |
number |
Index default (typically 40) |
Override the HNSW efSearch parameter. Higher values increase recall at the cost of speed. Must be β₯ topK. |
Returns: Promise<SearchResult[]> β array of results sorted by distance (ascending, lower = more similar).
SearchResult:
| Field | Type | Description |
|---|---|---|
text |
string |
The chunk text. If expandContext is true, this is the concatenation of the expanded chunks separated by \n\n. |
metadata |
ChunkMetadata & Record<string, any> |
Full chunk metadata including source_file, section_heading, url, doc_title, prev_chunk_id, next_chunk_id. When expanded, also includes _expanded: true and _contextChunks: number. |
distance |
number |
Cosine distance from the query vector. Range: [0, 2]. Lower = more similar. For normalized vectors, 0 = identical, 1 = orthogonal, 2 = opposite. |
id |
number |
Vector ID in the HNSW index. |
ChunkMetadata:
| Field | Type | Description |
|---|---|---|
chunk_id |
number |
Unique chunk identifier within the vROM. |
text |
string |
Original chunk text (before context expansion). |
source_file |
string |
Source document filename (e.g., 'transformers/quicktour.md'). |
section_heading |
string |
Markdown heading for this chunk's section. |
prev_chunk_id |
number | null |
Previous chunk in the document, or null if this is the first chunk. |
next_chunk_id |
number | null |
Next chunk in the document, or null if this is the last chunk. |
url |
string |
Source URL for citation. |
doc_title |
string |
Document title. |
_expanded? |
boolean |
Set to true when context expansion was applied. |
_contextChunks? |
number |
Total number of chunks in the expanded text. |
Throws:
'No vROM mounted β call mount() first''Embedding model not loaded'- Worker embedding errors
Example:
// Basic search
const results = await memory.search('how to tokenize text', { topK: 3 });
for (const r of results) {
console.log(`[${r.distance.toFixed(4)}] ${r.metadata.section_heading}`);
console.log(r.text.slice(0, 200));
console.log(`Source: ${r.metadata.url}\n`);
}
// With context expansion β gets surrounding chunks for more context
const expanded = await memory.search('pipeline API', {
topK: 3,
expandContext: true,
contextWindow: 2, // 2 chunks before + 2 chunks after
});
// Each result.text now contains up to 5 chunks of text
formatContext(results, options?)
formatContext(results: SearchResult[], options?: FormatContextOptions): string
Format search results into a string suitable for LLM context/system prompt injection.
Parameters:
| Param | Type | Description |
|---|---|---|
results |
SearchResult[] |
Array of search results from search(). |
options |
FormatContextOptions |
Optional formatting configuration. |
FormatContextOptions:
| Option | Type | Default | Description |
|---|---|---|---|
includeSources |
boolean |
true |
Append [Source: <url>] after each result. |
maxTokens |
number |
Infinity |
Approximate token budget. Stops adding results when the budget is exceeded. Token count is estimated as ceil(text.length / 4). |
Returns: string β formatted context, with results separated by ---.
Example:
const results = await memory.search('LoRA fine-tuning', { topK: 5 });
const context = memory.formatContext(results, {
maxTokens: 2000,
includeSources: true,
});
// Output looks like:
// ## LoRA: Low-Rank Adaptation
// LoRA is a parameter-efficient fine-tuning method...
// [Source: https://huggingface.co/docs/peft/conceptual_guides/lora]
//
// ---
//
// ## Using LoRA with PEFT
// To fine-tune a model with LoRA...
// [Source: https://huggingface.co/docs/peft/tutorial/peft_model_config]
//
// ---
getMountStatus()
getMountStatus(): MountStatus
Get the current mount state. Returns a snapshot β the object is not live.
MountStatus:
| Field | Type | Description |
|---|---|---|
activeVrom |
string | null |
ID of the currently mounted vROM, or null. |
version |
string | null |
Version string from the vROM manifest. |
ready |
boolean |
true if both the HNSW index is loaded and the embedding model is ready. |
vectors |
number |
Number of vectors in the mounted index. 0 if nothing mounted. |
dim |
number |
Vector dimensionality. 0 if nothing mounted. |
model |
string | null |
Currently loaded embedding model ID (e.g., 'Xenova/all-MiniLM-L6-v2'). |
isReady (getter)
get isReady(): boolean
Returns true if the SDK is fully initialized, a vROM is mounted, and the embedding model is loaded. Equivalent to checking getMountStatus().ready after init().
listVroms()
async listVroms(): Promise<VromRegistryEntry[]>
List all available vROMs from the registry. Fetches the registry from CDN on first call, then caches in OPFS for 1 hour.
VromRegistryEntry:
| Field | Type | Description |
|---|---|---|
id |
string |
Unique vROM identifier (e.g., 'hf-transformers-docs'). |
name |
string |
Human-readable name. |
description |
string |
Short description. |
version |
string |
Semantic version. |
vectors |
number |
Number of vectors in the index. |
dimensions |
number |
Vector dimensionality. |
tokens |
number |
Approximate total tokens in the corpus. |
size_mb |
number |
Download size in megabytes. |
model |
string |
Required embedding model ID. |
tags |
string[] |
Tags for categorization. |
official |
boolean |
Whether this is an official vROM. |
files |
{ manifest: string, index: string, chunks: string } |
CDN URLs for the vROM files. |
Example:
const vroms = await memory.listVroms();
for (const v of vroms) {
const cached = await memory.isCached(v.id);
console.log(`${cached ? 'β' : ' '} ${v.id} β ${v.vectors} vectors, ${v.size_mb} MB`);
}
isCached(vromId)
async isCached(vromId: string): Promise<boolean>
Check whether a vROM is cached in OPFS. Returns true if the index file exists locally.
evict(vromId)
async evict(vromId: string): Promise<void>
Remove a vROM from the OPFS cache. Deletes all files (manifest, index) for that vROM. Does not affect the currently mounted vROM β call unmount() first if evicting the active one.
storageEstimate()
async storageEstimate(): Promise<StorageEstimate>
Get the browser's storage usage estimate.
StorageEstimate:
| Field | Type | Description |
|---|---|---|
used |
number |
Bytes currently used by the origin. |
quota |
number |
Total bytes available to the origin. |
onProgress(fn)
onProgress(fn: ((p: { file: string; loaded: number; total: number }) => void) | null): void
Set a global progress callback for embedding model downloads. This is separate from the mount() onProgress callback (which tracks vROM index downloads).
The callback fires when the background worker downloads ONNX model files. Pass null to remove the callback.
Example:
memory.onProgress(({ file, loaded, total }) => {
const pct = total > 0 ? (loaded / total * 100).toFixed(0) : '?';
updateProgressBar(`${file}: ${pct}%`);
});
destroy()
destroy(): void
Destroy the SDK instance. Frees the WASM HNSW graph and terminates the background worker. The OPFS cache is not cleared.
After calling destroy(), the instance cannot be reused. Create a new AgentMemory to start over.
Class: VromCache
Low-level OPFS cache and registry manager. Used internally by AgentMemory, but exported for advanced use cases.
import { VromCache } from 'vrom.js';
Constructor
new VromCache(registryUrl?: string)
| Param | Type | Default | Description |
|---|---|---|---|
registryUrl |
string |
HF Hub CDN | Custom registry JSON URL. |
Methods
| Method | Signature | Description |
|---|---|---|
getRegistry() |
Promise<VromRegistry> |
Fetch the vROM registry. Caches in OPFS with 1-hour TTL. |
resolve(id) |
Promise<VromRegistryEntry | null> |
Look up a vROM by ID or hub:// URI. |
list() |
Promise<VromRegistryEntry[]> |
List all vROMs from the registry. |
isCached(id) |
Promise<boolean> |
Check if a vROM index is in OPFS. |
getCachedManifest(id) |
Promise<VromManifest | null> |
Read the cached manifest for a vROM. |
loadIndex(id) |
Promise<string | null> |
Read the raw index JSON from OPFS. |
pull(id, entry, onProgress?) |
Promise<void> |
Download a vROM from CDN and write to OPFS. |
evict(id) |
Promise<void> |
Delete a vROM from OPFS. |
storageEstimate() |
Promise<StorageEstimate> |
Get browser storage usage. |
VromManifest:
| Field | Type | Description |
|---|---|---|
vrom_id |
string |
Unique identifier. |
version |
string |
Semantic version. |
description |
string |
Human-readable description. |
source |
string |
Source description. |
embedding_spec |
object |
Embedding configuration (see below). |
hnsw_config |
object |
HNSW parameters used to build the index. |
vector_count |
number |
Number of vectors. |
total_tokens |
number |
Approximate token count across all chunks. |
total_chunks |
number |
Number of chunks. |
corpus_hash |
string |
SHA-256 hash prefix of the corpus text. |
created_at |
string |
ISO 8601 build timestamp. |
chunk_strategy |
object |
Chunking parameters used during build. |
embedding_spec:
| Field | Type | Description |
|---|---|---|
model |
string |
HF model ID for the browser (e.g., 'Xenova/all-MiniLM-L6-v2'). |
model_source? |
string |
Original model source (e.g., 'sentence-transformers/all-MiniLM-L6-v2'). |
dimensions |
number |
Embedding dimensionality. |
quantization |
string |
Quantization format (e.g., 'q8'). |
distance_metric |
string |
Distance metric (e.g., 'cosine'). |
normalized |
boolean |
Whether embeddings are L2-normalized. |
Low-Level: VectorDB (WASM)
The raw WASM HNSW engine, exposed via wasm-bindgen. This is what AgentMemory uses internally. You can use it directly for custom vector search without the vROM/worker layer.
Note: This is exposed from the
wasm-pkg/directory, not from the mainvrom.jspackage export. It's documented here for completeness.
Constructor
new VectorDB(
dim: number,
metric?: string | null, // 'cosine' | 'euclidean' | 'dot_product' (default: 'cosine')
m?: number | null, // HNSW M parameter (default: 16)
ef_construction?: number | null, // (default: 128)
ef_search?: number | null, // (default: 40)
): VectorDB
Static Methods
| Method | Signature | Description |
|---|---|---|
VectorDB.load(json) |
load(json: string): VectorDB |
Deserialize a VectorDB from JSON. This is how vROM indexes are loaded. |
Instance Methods
| Method | Signature | Description |
|---|---|---|
insert(vector, metadata?) |
insert(v: Float32Array, m?: string | null): number |
Insert a vector with optional JSON metadata. Returns the assigned ID. |
insert_batch(vectors, n) |
insert_batch(v: Float32Array, n: number): number |
Insert n vectors from a flat Float32Array. Returns the first assigned ID. |
search(query, k) |
search(q: Float32Array, k: number): string |
Search for k nearest neighbors. Returns JSON string of [{id, distance, metadata}]. |
search_with_ef(query, k, ef) |
search_with_ef(q: Float32Array, k: number, ef: number): string |
Search with a custom efSearch parameter. |
get_vector(id) |
get_vector(id: number): Float32Array | undefined |
Retrieve the vector for a given ID. |
get_metadata(id) |
get_metadata(id: number): string | undefined |
Retrieve the metadata JSON string for a given ID. |
len() |
len(): number |
Number of vectors in the index. |
dim() |
dim(): number |
Vector dimensionality. |
stats() |
stats(): string |
JSON string with index statistics. |
save() |
save(): string |
Serialize the entire index to JSON. |
free() |
free(): void |
Free WASM memory. Call when done with the index. |
stats() output:
{
"num_vectors": 1356,
"dimensions": 384,
"max_layer": 3,
"total_connections": 42680,
"avg_connections_per_node": 31.47,
"memory_bytes": 2456320
}
Embed Worker Protocol
The background worker communicates with the main thread via postMessage. All outgoing messages are tagged with source: 'vecdb' to avoid collisions with transformers.js internal messages.
Main β Worker
| Message | Fields | Description |
|---|---|---|
load |
{ type: 'load', modelId: string, dtype: string } |
Load an embedding model. If the same model is already loaded, returns immediately with cached: true. |
embed |
{ type: 'embed', texts: string[], id: string } |
Embed a batch of texts. The id is used to correlate responses. |
unload |
{ type: 'unload' } |
Dispose the current model and free memory. |
get-model |
{ type: 'get-model' } |
Query the currently loaded model. |
Worker β Main
| Message | Fields | Description |
|---|---|---|
ready |
{ status: 'ready', dim, modelId, dtype, cached, source: 'vecdb' } |
Model is loaded and ready. dim is the embedding dimensionality. |
result |
{ status: 'result', id, embeddings: Float32Array, dims, source: 'vecdb' } |
Embedding result. embeddings is transferred (zero-copy). |
dl-progress |
{ status: 'dl-progress', file, loaded, total, source: 'vecdb' } |
Model download progress. |
error |
{ status: 'error', id?, message, source: 'vecdb' } |
Error during load or embed. |
unloaded |
{ status: 'unloaded', source: 'vecdb' } |
Model successfully unloaded. |
model-info |
{ status: 'model-info', modelId, dtype, dim, loaded, source: 'vecdb' } |
Response to get-model. |
Type Index
All types exported from the package:
| Type | Category | Description |
|---|---|---|
AgentMemoryOptions |
Config | Constructor options for AgentMemory |
MountOptions |
Config | Options for mount() |
SearchOptions |
Config | Options for search() |
FormatContextOptions |
Config | Options for formatContext() |
MountStatus |
State | Current mount state snapshot |
SearchResult |
Result | Single search result with text, metadata, and distance |
ChunkMetadata |
Result | Metadata fields stored per chunk in the HNSW index |
DownloadProgress |
Event | Progress event during vROM download |
StorageEstimate |
State | Browser storage usage |
VromRegistry |
Registry | Full registry object |
VromRegistryEntry |
Registry | Single vROM entry from the registry |
VromManifest |
Registry | Full manifest stored inside a vROM |