← All @molecule/* packages · App templates

@molecule/api-ai-vector-store

Core interface · ai-vector-store · API (Node) · v1.0.1 · Apache-2.0

Vector store core interface — named collections of embedding vectors with upsert and similarity query (metadata filters, topK) via swappable providers (pgvector, Pinecone, Chroma, memory).

npm install @molecule/api-ai-vector-store

npm · Source on GitHub

How it works

@molecule/api-ai-vector-store is the ai-vector-store core interface on the API (Node) side: the API your app calls, with no vendor inside.

Choose the implementation by bonding one of its 4 providers: @molecule/api-ai-vector-store-chroma, @molecule/api-ai-vector-store-memory, @molecule/api-ai-vector-store-pgvector, @molecule/api-ai-vector-store-pinecone.

import { setProvider, requireProvider } from '@molecule/api-ai-vector-store'
import { provider as memory } from '@molecule/api-ai-vector-store-memory'

// Wire at startup — memory for dev; swap to pgvector/pinecone when provisioned.
setProvider(memory)

const store = requireProvider()
await store.createCollection({ name: 'docs', dimension: 1536, metric: 'cosine' })
await store.upsert({
  collection: 'docs',
  records: [{ id: 'a', embedding: vec, content: 'PTO policy…', metadata: { userId: 'u1' } }],
})
const hits = await store.query({
  collection: 'docs',
  embedding: queryVec,
  topK: 5,
  filter: [{ field: 'userId', operator: 'eq', value: 'u1' }],
})

Providers (4): @molecule/api-ai-vector-store-chroma, @molecule/api-ai-vector-store-memory, @molecule/api-ai-vector-store-pgvector, @molecule/api-ai-vector-store-pinecone

Works with: @molecule/api-bond

Reference

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

AI vector-store core interface for molecule.dev.

Defines the AIVectorStoreProvider contract — named collections of embedding vectors with upsert, similarity query (metadata filters, topK, minScore), fetch, and delete — plus the accessor (setProvider/ getProvider/hasProvider/requireProvider). Interface-only: bond a provider package (@molecule/api-ai-vector-store-pgvector, -pinecone, -chroma, or -memory for dev/tests).

Quick Start

import { setProvider, requireProvider } from '@molecule/api-ai-vector-store'
import { provider as memory } from '@molecule/api-ai-vector-store-memory'

// Wire at startup — memory for dev; swap to pgvector/pinecone when provisioned.
setProvider(memory)

const store = requireProvider()
await store.createCollection({ name: 'docs', dimension: 1536, metric: 'cosine' })
await store.upsert({
  collection: 'docs',
  records: [{ id: 'a', embedding: vec, content: 'PTO policy…', metadata: { userId: 'u1' } }],
})
const hits = await store.query({
  collection: 'docs',
  embedding: queryVec,
  topK: 5,
  filter: [{ field: 'userId', operator: 'eq', value: 'u1' }],
})

Type

core

Installation

npm install @molecule/api-ai-vector-store @molecule/api-bond

API

Interfaces

AIVectorStoreConfig

Base configuration for vector store providers.

interface AIVectorStoreConfig {
  /** Connection string or URL for the vector store. */
  connectionString?: string
  /** API key for managed vector store services. */
  apiKey?: string
  /** Additional provider-specific options. */
  [key: string]: unknown
}

AIVectorStoreProvider

AIVectorStore provider interface.

Each bond package (pgvector, Pinecone, Chroma, etc.) implements this interface to provide vector database operations.

interface AIVectorStoreProvider {
  /** Provider name identifier. */
  readonly name: string

  /**
   * Create a new collection/namespace for storing vectors.
   *
   * Idempotent: re-creating a collection that already exists with the SAME
   * dimension is a no-op, so callers can safely call this at startup on every
   * boot. Only a genuine dimension CONFLICT (same name, different dimension)
   * throws. Providers MUST implement this contract so an app that works against
   * one bond (e.g. the in-memory store in dev) behaves identically against
   * another (e.g. pgvector in prod) instead of crashing on the second boot.
   *
   * @param params - Collection creation parameters.
   * @throws {Error} if a collection with the same name exists at a different dimension.
   */
  createCollection(params: CreateCollectionParams): Promise<void>

  /**
   * Delete a collection/namespace and all its vectors.
   *
   * @param name - Name of the collection to delete.
   */
  deleteCollection(name: string): Promise<void>

  /**
   * List all available collections.
   *
   * @returns Array of collection names.
   */
  listCollections(): Promise<string[]>

  /**
   * Upsert (insert or update) vector records into a collection.
   *
   * @param params - Upsert parameters including collection and records.
   */
  upsert(params: VectorUpsertParams): Promise<void>

  /**
   * Query for similar vectors using a query embedding.
   *
   * @param params - Query parameters including embedding, topK, and filters.
   * @returns Array of search results sorted by similarity (highest first).
   */
  query(params: VectorQueryParams): Promise<VectorSearchResult[]>

  /**
   * Fetch vector records by their IDs.
   *
   * @param params - Fetch parameters including collection and IDs.
   * @returns Array of found vector records (missing IDs are omitted).
   */
  fetch(params: VectorFetchParams): Promise<VectorRecord[]>

  /**
   * Delete vector records by their IDs.
   *
   * @param params - Delete parameters including collection and IDs.
   */
  delete(params: VectorDeleteParams): Promise<void>
}

CreateCollectionParams

Parameters for creating a collection/namespace.

interface CreateCollectionParams {
  /** Name of the collection to create. */
  name: string
  /** Dimensionality of vectors in this collection. */
  dimension: number
  /** Distance metric for similarity search. Defaults to 'cosine'. */
  metric?: DistanceMetric
}

VectorDeleteParams

Parameters for deleting vectors.

interface VectorDeleteParams {
  /** The collection/namespace to delete from. */
  collection: string
  /** IDs of vectors to delete. */
  ids: string[]
}

VectorFetchParams

Parameters for fetching vectors by ID.

interface VectorFetchParams {
  /** The collection/namespace to fetch from. */
  collection: string
  /** IDs of vectors to fetch. */
  ids: string[]
}

VectorQueryParams

Parameters for similarity search queries.

interface VectorQueryParams {
  /** The query embedding vector to find similar vectors for. */
  embedding: number[]
  /** Maximum number of results to return. Defaults to 10. */
  topK?: number
  /** Optional metadata filters to narrow results. */
  filter?: MetadataFilter[]
  /** Minimum similarity score threshold (0–1). Results below this are excluded. */
  minScore?: number
  /** The collection/namespace to query. */
  collection: string
}

VectorRecord

A stored vector record with its embedding, metadata, and optional content.

interface VectorRecord {
  /** Unique identifier for this vector record. */
  id: string
  /** The embedding vector (array of floats). */
  embedding: number[]
  /** Arbitrary metadata associated with this vector. */
  metadata?: Record<string, unknown>
  /** Optional text content that produced this embedding. */
  content?: string
}

VectorRecordInput

Input for upserting a vector record. Same as VectorRecord but embedding is optional when the store handles embedding generation internally.

interface VectorRecordInput {
  /** Unique identifier for this vector record. */
  id: string
  /** The embedding vector (array of floats). */
  embedding: number[]
  /** Arbitrary metadata associated with this vector. */
  metadata?: Record<string, unknown>
  /** Optional text content that produced this embedding. */
  content?: string
}

VectorSearchResult

A result from a similarity search query.

interface VectorSearchResult {
  /** The matched vector record. */
  record: VectorRecord
  /** Similarity score (higher is more similar, normalized 0–1 when possible). */
  score: number
}

VectorUpsertParams

Parameters for upserting vectors.

interface VectorUpsertParams {
  /** The collection/namespace to upsert into. */
  collection: string
  /** Vector records to upsert. */
  records: VectorRecordInput[]
}

Types

DistanceMetric

Distance metric for similarity calculations.

type DistanceMetric = 'cosine' | 'euclidean' | 'inner_product'

MetadataFilter

Metadata filter operators for querying vectors.

type MetadataFilter =
  | { field: string; operator: 'eq'; value: string | number | boolean }
  | { field: string; operator: 'ne'; value: string | number | boolean }
  | { field: string; operator: 'gt'; value: number }
  | { field: string; operator: 'gte'; value: number }
  | { field: string; operator: 'lt'; value: number }
  | { field: string; operator: 'lte'; value: number }
  | { field: string; operator: 'in'; value: (string | number)[] }

Functions

getProvider()

Get the active vector store provider, or null if none is configured.

function getProvider(): AIVectorStoreProvider | null

Returns: The current provider or null.

hasProvider()

Check whether a vector store provider is configured.

function hasProvider(): boolean

Returns: True if a provider has been set.

requireProvider()

Get the active vector store provider, throwing if none is configured.

function requireProvider(): AIVectorStoreProvider

Returns: The current provider.

setProvider(provider)

Set the active vector store provider.

function setProvider(provider: AIVectorStoreProvider): void
  • provider — The vector store provider to register.

Available Providers

ProviderPackage
Ai Vector Store@molecule/api-ai-vector-store-chroma
Ai Vector Store@molecule/api-ai-vector-store-memory
Ai Vector Store@molecule/api-ai-vector-store-pgvector
Ai Vector Store@molecule/api-ai-vector-store-pinecone

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-bond ^1.0.1

Runtime Dependencies

  • @molecule/api-bond

  • Wire it at startup with setProvider(...) — or the equivalent bond('ai-vector-store', provider). This core routes through the shared @molecule/api-bond registry, so either call registers the same provider and validateBonds() reports it as missing when unwired.

  • Pick the bond by what is actually provisioned. -memory needs nothing but holds vectors in process memory (lost on restart — dev/tests only). -pgvector reuses the app's existing Postgres (DATABASE_URL) and provisions its own extension/tables. Managed stores (Pinecone, Chroma) require their service and key to actually exist — don't wire one on the assumption that it does.

  • This store does NOT embed. upsert takes precomputed embedding vectors — pair it with @molecule/api-ai-embeddings, or use @molecule/api-semantic-search (composes both) / @molecule/api-ai-rag (grounded Q&A) instead of calling this directly.

  • One collection = one embedding model + dimension. createCollection fixes dimension; upserting vectors from a different model/dimension corrupts search results (or throws). Re-embed the corpus when switching models.

  • Scope multi-tenant data. Put the owner (user/tenant id) in metadata and filter on it in EVERY query (or use per-tenant collections) — a shared, unfiltered collection leaks one tenant's documents into another's results.

  • query results are sorted by score (higher = more similar, 0–1 where possible); use minScore to drop weak matches rather than trusting topK alone.

E2E Tests

Integration checklist — drive the real flow (no mocks): upsert real vectors, run real query calls, and verify through the FEATURE this store powers (semantic search / RAG retrieval / related-items) plus direct property checks on the returned VectorSearchResult[]. Adapt each item to this app's actual corpus/screens and check every box off. A box you can't check is an integration bug to fix — not a skip:

  • upsert records (each with a stable id + metadata), then query with an embedding: results come back ranked by score (highest first), the semantically closest stored item is result #1 and unrelated items rank lower — the whole point. score is a sane similarity (bounded, ~0–1, higher = closer) and each hit's record.id / record.metadata come back intact.
  • topK is honored: a query with topK: k returns AT MOST k results, best-first — never more, never unordered.
  • Metadata filter works: a query carrying a MetadataFilter (e.g. { field: 'userId', operator: 'eq', value }) returns only records matching the filter and never leaks non-matching ones.
  • Collection/namespace ISOLATION: a query scoped to one collection never returns another collection's vectors — the multi-tenant boundary that keeps one user's private docs out of another's results. Confirm with two collections (or two owner ids) that a scoped query returns only its own.
  • delete removes a record: after delete({ collection, ids }) the vector stops appearing in query results (and fetch omits it).
  • The feature built on the store returns MEANING-ranked results end-to-end in the UI — a semantic-search / RAG / related-items query surfaces the relevant items first, not a keyword or insertion-order match. This store does NOT embed text itself, so confirm it composes with @molecule/api-ai-embeddings (query text → embedding → query).
  • Every upsert / query runs SERVER-SIDE — the provider/store key stays on the server and never ships in the browser bundle (the package is server-only; a client import throws by design).