npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@devilsdev/rag-pipeline-utils

v3.3.0

Published

Composable retrieval-augmented generation (RAG) for Node.js: grounded citations, evaluation, guardrails, hybrid retrieval and a CLI.

Readme

rag-pipeline-utils

Retrieval-augmented generation for Node.js, with answers you can check. One createRagPipeline() call wires an embedder, a retriever, an optional reranker and an LLM. Citations, evaluation, guardrails and token budgets are opt-in layers on top, and every part is a plain JavaScript contract you can replace with your own code.

npm install @devilsdev/rag-pipeline-utils

This runs offline, with the built-in TF-IDF embedder and an in-memory vector store:

import {
  createRagPipeline,
  LocalEmbedder,
  MemoryRetriever,
} from "@devilsdev/rag-pipeline-utils";

const docs = [
  {
    id: "vacation",
    content:
      "Full-time employees receive twenty days of paid vacation per year.",
  },
  {
    id: "remote",
    content: "Remote work is allowed two days per week with manager approval.",
  },
];

// 1. Fit the embedder to your corpus and index the documents.
const embedder = new LocalEmbedder();
embedder.train(docs.map((doc) => doc.content));

const retriever = new MemoryRetriever();
await retriever.store(
  docs.map((doc) => ({ ...doc, vector: embedder.embed(doc.content) })),
);

// 2. Build the pipeline and ask a question.
const pipeline = createRagPipeline({ embedder, retriever });
const result = await pipeline.run({
  query: "How many vacation days do I get?",
});

console.log(result.results[0].id); // "vacation"
console.log(result.answer); // null: no LLM configured, so retrieval only

Why this library

  • Grounded by default. Answers come back with the passages they were built from, sentence-level citations and a groundedness score, including checks that numbers in the answer appear in the sources and that it doesn't negate them.
  • Measured, not guessed. rag-pipeline eval scores a test set and fails CI when answers regress; rag-eval-action posts the result on every pull request. Retrieval is benchmarked on BEIR SciFact.
  • Provider-neutral. OpenAI, Anthropic, Cohere and Ollama connectors; PostgreSQL with pgvector and Qdrant stores; an offline TF-IDF embedder. Anything with an embed() or generate() method works too, including Vercel AI SDK models.
  • Production behaviour. Cancellation and timeouts on every stage, retries only on transient errors, ACL filtering before generation, PII redaction, caching, and a token budget for the context sent to the model.
  • Built to extend. Each stage is a small contract, and runContractTests() tests your own plugin against what the pipeline relies on.
  • A CLI that does real work. init, ingest, query, eval and serve run against a persistent local index, fully offline if you want.

Contents

Installation

npm install @devilsdev/rag-pipeline-utils

Requires Node.js 22 or later (2.x runs on Node.js 18 and later). The package ships CommonJS, ESM and TypeScript declarations. It also runs on Cloudflare Workers with the nodejs_compat flag, and @devilsdev/rag-pipeline-utils/edge runs without Node.js APIs, on Vercel Edge Functions, Workers without the flag, Deno and Netlify Edge (Edge runtimes).

You can also install only the parts you use: @devilsdev/rag-core (the pipeline), @devilsdev/rag-connectors, @devilsdev/rag-eval and @devilsdev/rag-guardrails. They are the full package's own parts, the same objects; rag-eval alone installs about 6 MB, against 33 MB for the full package. See Packages.

Optional peer dependencies, installed only by projects that use them:

| Package | Needed for | | -------------------- | --------------------------------------------- | | openai | OpenAIConnector | | pg | PgVectorRetriever | | isolated-vm | the experimental PluginSandbox (version 6+) | | pino-pretty | pretty-printed logs | | @opentelemetry/api | OpenTelemetry spans (telemetry) |

Upgrading from 2.x? The 3.0 migration guide lists the changes to make.

npm install failed with husky: not found? Versions 2.0.0 to 2.6.1 ran a development hook on install. Install 2.6.2 or later: npm install @devilsdev/rag-pipeline-utils@latest.

Quick start with an LLM

To generate answers, add an LLM (npm install openai for OpenAIConnector). The same connector can also embed:

import {
  createRagPipeline,
  OpenAIConnector,
  MemoryRetriever,
} from "@devilsdev/rag-pipeline-utils";

const openai = new OpenAIConnector({ apiKey: process.env.OPENAI_API_KEY });

const retriever = new MemoryRetriever();
const policy =
  "Full-time employees receive twenty days of paid vacation per year.";
await retriever.store([
  { id: "vacation", content: policy, vector: await openai.embed(policy) },
]);

const pipeline = createRagPipeline({
  embedder: openai,
  retriever,
  llm: openai,
});
const result = await pipeline.run({
  query: "How many vacation days do I get?",
  options: { citations: true, evaluate: true },
});

console.log(result.answer);
console.log(result.citations.groundednessScore); // 0..1, share of grounded sentences
console.log(result.evaluation.scores); // { faithfulness, relevance, contextPrecision, groundedness }

Command line

The rag-pipeline CLI builds a local index from your files and answers questions against it.

npx rag-pipeline init                      # writes .ragrc.json (interactive in a terminal)
npx rag-pipeline ingest ./docs             # indexes .md, .html, .csv and .txt files
npx rag-pipeline query "What is the remote work policy?"
npx rag-pipeline serve --port 3000         # local HTTP API: GET /health, POST /query
npx rag-pipeline doctor                    # checks config, API keys, plugins and the index
npx rag-pipeline generate-dataset --output tests.json     # drafts a test set from the index with your llm
npx rag-pipeline eval tests.json --min faithfulness=0.8   # scores a test set; exits 1 on failure

The default local template needs no API keys. Use init --template openai, anthropic or ollama to generate answers with a model. Other commands include validate, hub install for plugins and ai benchmark for measured latency.

query can also show its work: --explain lists each passage's score and which passages support each sentence, --trace times each stage, --stats estimates tokens and cost, and --streaming prints the answer as it is generated:

npx rag-pipeline query "How many vacation days do I get?" --explain --trace

See the CLI reference.

Use cases

Answer questions with sources your users can check

Citations map every sentence of the answer to the passages that support it. A sentence whose facts or numbers are missing from the sources is reported as ungrounded, and so is one that negates its source ("employees never receive paid vacation" against "employees receive twenty days").

import { CitationTracker } from "@devilsdev/rag-pipeline-utils";

const sources = [
  {
    id: "policy",
    content: "Employees receive twenty days of paid vacation per year.",
  },
];
const tracker = new CitationTracker();

const good = tracker.track(
  "Employees receive twenty days of paid vacation per year.",
  sources,
);
const wrong = tracker.track(
  "Employees receive thirty days of paid vacation per year.",
  sources,
);

console.log(good.groundednessScore); // 1
console.log(wrong.groundednessScore); // 0: the number does not match the source

Measure answer quality in CI

PipelineEvaluator scores faithfulness, relevance, context precision and, when you supply a reference answer, context recall. Run it over a fixed question set and fail the build when scores drop.

import { PipelineEvaluator } from "@devilsdev/rag-pipeline-utils";

const evaluator = new PipelineEvaluator();
const report = evaluator.evaluate(
  {
    query: "How many vacation days do employees get?",
    answer: "Employees receive twenty days of paid vacation per year.",
    results: [
      { content: "Employees receive twenty days of paid vacation per year." },
    ],
  },
  { referenceAnswer: "Twenty days of paid vacation per year." },
);

console.log(report.scores); // includes contextRecall because a reference was given
if (report.scores.faithfulness < 0.8) process.exitCode = 1;

From the command line, rag-pipeline eval runs the whole set, saves a report and fails the job when scores fall below a minimum or drop from a saved baseline:

npx rag-pipeline eval tests.json --min faithfulness=0.8 --output main.json   # on main
npx rag-pipeline eval tests.json --baseline main.json                        # on a pull request

The recording runs offline with the local embedder and a stand-in LLM; its files are in assets/eval-demo.

Keep the question set in a JSON file of { prompt, expected, sourceIds } cases; generateSyntheticDataset (or rag-pipeline generate-dataset) drafts one from your documents for you to review. validateDataset checks it before a run and reports every malformed case, with its index and field; runEvaluation runs it and saves a JSON report, which renderEvaluationReport turns into Markdown or HTML; and compareConfigurations compares two pipelines, or a pipeline against the report saved from your main branch, and lists the cases that got worse. See the dataset format.

On GitHub, DevilsDev/rag-eval-action runs this on every pull request, compares it with your main branch and posts the summary as a comment.

Check answers from another framework

Already on LangChain, Mastra, the AI SDK or LlamaIndex? checkAnswer checks the answer your chain produced against the sources it was given, in the shape your framework returns them:

import { checkAnswer } from "@devilsdev/rag-pipeline-utils";

const check = await checkAnswer({
  question: "How many vacation days do I get?",
  answer: "Full-time employees receive thirty days of paid vacation per year.",
  sources: [
    {
      pageContent:
        "Full-time employees receive twenty days of paid vacation per year.",
      metadata: { source: "handbook.md" },
    },
  ],
});

console.log(check.grounded); // false
console.log(check.unsupported.length); // 1

On Mastra, createMastraScorer({ createScorer }) runs the same check as an agent scorer, with no model calls, and createMastraGuardrails() adds injection detection and PII redaction as a processor (Mastra docs).

Ground an AI SDK app

Already using the Vercel AI SDK? groundingMiddleware adds retrieval, answer checks and guardrails to any AI SDK model, and your generateText and streamText calls stay as they are:

import { generateText, wrapLanguageModel } from "ai";
import { openai } from "@ai-sdk/openai";
import { groundingMiddleware } from "@devilsdev/rag-pipeline-utils";

const model = wrapLanguageModel({
  model: openai("gpt-4o-mini"),
  middleware: groundingMiddleware({ retriever, embedder }),
});

const { text, sources, providerMetadata } = await generateText({
  model,
  prompt: "How many vacation days do I get?",
});
console.log(providerMetadata.ragPipeline.grounded); // false if a sentence is unsupported

Each call retrieves passages for the last user message, gives them to the model as untrusted reference data, checks the answer against them, and returns them as sources. The ACL, injection and PII guards are options. See the middleware docs.

Test your RAG code offline

@devilsdev/rag-pipeline-utils/testing has a deterministic embedder, an LLM that echoes the top passage and records its calls, and fixture documents, so tests need no network or API keys:

import { createTestPipeline } from "@devilsdev/rag-pipeline-utils/testing";

const { pipeline, llm } = await createTestPipeline();
const result = await pipeline.run({
  query: "How many vacation days do I get?",
});

console.log(result.results[0].id); // "vacation"
console.log(llm.calls.length); // 1

expect.extend(ragMatchers) adds toBeGroundedIn, toCite and toContainNoPII to Jest and Vitest, so expect(result).toBeGroundedIn() fails a test when an answer says something its sources don't (matchers).

Writing your own plugin? runContractTests("retriever", () => new MyRetriever()) from the same entry registers tests for the behaviour the pipeline relies on, in Jest, Vitest, Mocha or node:test (contract tests).

Protect an internal assistant

GuardrailsPipeline wraps any pipeline. Access control runs before the LLM sees a document, prompt-injection detection runs on the query and, with detectInjection, on the retrieved documents too (indirect injection: instructions planted in a page or file you index), and PII is redacted from the answer, its citations and its evaluation details.

import {
  createRagPipeline,
  GuardrailsPipeline,
  OpenAIConnector,
} from "@devilsdev/rag-pipeline-utils";

const openai = new OpenAIConnector({ apiKey: process.env.OPENAI_API_KEY });
const retriever = {
  // Any object with retrieve() works; requiredRole drives access control.
  async retrieve() {
    return [
      {
        id: "handbook",
        content: "The handbook covers vacation.",
        metadata: {},
      },
      {
        id: "salaries",
        content: "Executive salaries ...",
        metadata: { requiredRole: "exec" },
      },
    ];
  },
};

const assistant = new GuardrailsPipeline(
  createRagPipeline({ retriever, llm: openai }),
  {
    preRetrieval: { enableInjectionDetection: true },
    retrieval: { enforceACL: true, detectInjection: true },
    postGeneration: { enablePIIDetection: true },
    strict: true, // block instead of warn
  },
);

const result = await assistant.run({
  query: "What does the handbook cover?",
  context: { userPermissions: ["employee"] }, // "salaries" never reaches the LLM
});
console.log(result.guardrails.retrieval.removed); // [{ id: "salaries" }]

Combine keyword and vector search

HybridRetriever merges any retrievers with Reciprocal Rank Fusion. BM25 finds exact terms such as product codes; vectors find paraphrases.

import {
  BM25Search,
  HybridRetriever,
  LocalEmbedder,
  MemoryRetriever,
} from "@devilsdev/rag-pipeline-utils";

const docs = [
  {
    id: "err-4012",
    content: "Error E4012 means the API token expired. Generate a new token.",
  },
  {
    id: "billing",
    content: "Invoices are emailed on the first business day of each month.",
  },
];

const bm25 = new BM25Search();
bm25.index(docs);

const embedder = new LocalEmbedder();
embedder.train(docs.map((doc) => doc.content));
const vectors = new MemoryRetriever();
await vectors.store(
  docs.map((doc) => ({ ...doc, vector: embedder.embed(doc.content) })),
);

const hybrid = new HybridRetriever([
  { retriever: bm25, weight: 1, name: "bm25" },
  { retriever: vectors, weight: 1, name: "vectors" },
]);
const results = await hybrid.retrieve({
  query: "what does E4012 mean",
  queryVector: embedder.embed("what does E4012 mean"),
  topK: 2,
});
console.log(results[0].id); // "err-4012"

On the BEIR SciFact benchmark, BM25Search alone matches the published BM25 baseline (nDCG@10 0.665); fusion helps when the vector side is a strong embedder, so weight the retrievers to suit. See retrieval quality.

Answer multi-part questions

AgenticPipeline splits compound questions into sub-queries, retrieves for each, and self-checks the answer against the sources before returning it.

import {
  AgenticPipeline,
  MemoryRetriever,
  OpenAIConnector,
} from "@devilsdev/rag-pipeline-utils";

const openai = new OpenAIConnector({ apiKey: process.env.OPENAI_API_KEY });
const retriever = new MemoryRetriever();
const policies = [
  "Full-time employees receive twenty days of paid vacation per year.",
  "Remote work is allowed two days per week with manager approval.",
];
await retriever.store(
  await Promise.all(
    policies.map(async (content, i) => ({
      id: `p${i}`,
      content,
      vector: await openai.embed(content),
    })),
  ),
);

const agent = new AgenticPipeline();
const result = await agent.run({
  query: "How much vacation do I get, and can I work from home?",
  retriever,
  llm: openai,
  embedder: openai, // each sub-query gets its own embedding
});
console.log(result.subQueries.map((q) => q.subQuery));
console.log(result.answer);

Fit retrieved context into a token budget

maxContextTokens keeps the documents sent to the LLM within a budget: it keeps the best-ranked ones that fit, cuts the top one at a word boundary when it alone is too long, and reports what it left out.

const result = await pipeline.run({
  query: "How many vacation days do employees get?",
  options: { topK: 10, maxContextTokens: 2000 },
});

console.log(result.packing); // { tokens, maxTokens: 2000, kept, dropped, truncated }

packContext(documents, { maxTokens, countTokens }) does the same outside a run; pass your model's tokenizer as countTokens for exact counts.

Keep request latency bounded

Every run accepts a timeout and an AbortSignal. The signal is passed to the embedder, retriever, reranker and LLM, so cancelled work stops instead of running in the background.

import {
  createRagPipeline,
  OpenAIConnector,
  MemoryRetriever,
} from "@devilsdev/rag-pipeline-utils";

const openai = new OpenAIConnector({ apiKey: process.env.OPENAI_API_KEY });
const pipeline = createRagPipeline({
  embedder: openai,
  retriever: new MemoryRetriever(),
  llm: openai,
});

const controller = new AbortController(); // e.g. aborted when the HTTP client disconnects
const result = await pipeline.run({
  query: "Summarise the travel policy",
  options: { timeout: 10_000, signal: controller.signal },
});
if (!result.success) console.error(result.error); // "Execution timeout" or "Execution aborted"

Cache repeated questions

cache: true caches query embeddings, retrieval results and answers in memory, so a repeated question makes no model calls. Use RedisCache to share the cache between processes. Cached results are not reused when the index, embedder, model or its settings change, and access-control filtering still runs on every request:

import { createRagPipeline } from "@devilsdev/rag-pipeline-utils";
import {
  createTestPipeline,
  EchoLLM,
} from "@devilsdev/rag-pipeline-utils/testing";

const { embedder, retriever } = await createTestPipeline();
const llm = new EchoLLM();
const pipeline = createRagPipeline({ embedder, retriever, llm, cache: true });

await pipeline.run({ query: "How many vacation days do I get?" });
const again = await pipeline.run({ query: "How many vacation days do I get?" });

console.log(again.cache.generation); // "hit"
console.log(llm.calls.length); // 1

Answers are cached only at temperature 0. See Caching.

Run fully local

Pair the LocalEmbedder or Ollama embeddings with an Ollama model and FileVectorStore for a private, offline setup. The CLI's local and ollama templates set this up for you:

npx rag-pipeline init --no-interactive --template ollama
npx rag-pipeline ingest ./docs
npx rag-pipeline serve

How it works

             ┌──────────────── GuardrailsPipeline (optional) ─────────────────┐
query ──▶    │ injection check ─▶ embed ─▶ retrieve ─▶ ACL / relevance filter │
             │   ─▶ rerank ─▶ LLM ─▶ citations ─▶ evaluation ─▶ PII redaction │ ──▶ result
             └────────────────────────────────────────────────────────────────┘

createRagPipeline() runs embed → retrieve → rerank → generate, then citations and evaluation when requested. Each stage receives the run's AbortSignal, and a timeout or abort stops the remaining stages. GuardrailsPipeline, AgenticPipeline and HybridRetriever compose around or inside it; they are not hidden steps of the default pipeline.

The result of run() is:

{
  success: boolean;
  query: string;
  results: Array<{ id; content; score; metadata }>;
  answer: string | null;            // null when no LLM is configured
  citations?: { citations; groundednessScore; hallucinationReport };
  evaluation?: { scores; details; metadata };
  packing?: { tokens; maxTokens; kept; dropped; truncated }; // with maxContextTokens
  cache?: { embeddings; retrieval; generation };             // with a cache
  route?: { class; model; estimatedCost };                   // with createModelRouter
  timing?: { totalMs };                                      // ms since run() was called
  error?: string;                   // set when success is false
}

Capabilities

| Area | What you get | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Chunking | ChunkingEngine with sentence, fixed-size, recursive, semantic and structure-aware strategies | | Retrieval | MemoryRetriever, persistent FileVectorStore, PgVectorRetriever (PostgreSQL), QdrantRetriever, BM25Search, HybridRetriever (Reciprocal Rank Fusion) | | Reranking | ScoringReranker, EmbeddingReranker (cached), CascadeReranker | | Citations | Per-sentence source mapping, hallucination report, numeric and negation checks | | Evaluation | Faithfulness, relevance, context precision, context recall (with a reference), groundedness, BLEU/ROUGE, semantic similarity with any embedder; test sets with validateDataset, runEvaluation, compareConfigurations, generateSyntheticDataset and rag-pipeline eval | | Integrations | groundingMiddleware for any AI SDK model and Mastra scorers and guardrails; checkAnswer for answers from LangChain, LlamaIndex, Mastra or the AI SDK; createAiSdkAdapter | | Caching | Opt-in caches for query embeddings, retrieval and answers, in memory (MemoryCache) or Redis (RedisCache) | | Testing | /testing entry: offline HashEmbedder, EchoLLM, fixtures, createTestPipeline(); contract tests for your plugins with runContractTests() and checkContract() | | Guardrails | Injection detection on queries and retrieved documents, with input normalisation; ACL and relevance filtering before generation; PII redaction | | Agentic | QueryPlanner, IterativeRetriever, SelfCritiqueChecker, AgenticPipeline | | GraphRAG | KnowledgeGraph, EntityExtractor, GraphRetriever | | Streaming | Token streaming with a final chunk carrying citations, evaluation and the time to first token; SSEAdapter, WebSocketAdapter | | Cost | CostTracker, TokenBudget, CostCalculator with sourced, overridable pricing; packContext() and maxContextTokens fit retrieved documents into a token budget; createModelRouter sends each query to the cheapest model suited to it | | Operations | DevServer HTTP API, ExecutionTracer, metrics (counters, gauges, histograms), eventLogger, coded errors with suggestions (createError), AuditLogger, MCP tool definitions (MCPServer) and an MCP server example for Claude and other MCP clients; OpenTelemetry spans with telemetry: true |

How it compares

A short summary of the comparison page (as of November 2026). Mastra and the AI SDK are often used together with this library rather than instead of it.

| | rag-pipeline-utils | LangChain.js | Mastra | Vercel AI SDK | | ------------- | ---------------------------------------------------------------------------------------- | ---------------------------------- | ------------------------------------ | --------------------------------------- | | Focus | RAG with grounding, evaluation and guardrails | General-purpose LLM orchestration | Agents and workflows | Model calls, streaming, tools, UI hooks | | Evaluation | Deterministic metrics, no model calls; CLI and GitHub Action that fail CI on regressions | openevals (LLM judge), LangSmith | LLM-judge scorers in @mastra/evals | None built in | | Citations | Per sentence, with a groundedness score and number and negation checks | Wired up by hand | Wired up by hand | Passes provider citations through | | Guardrails | ACL before generation, injection detection (pattern-based), PII redaction | Via integrations | Model-based processors | Middleware you write | | Vector stores | Memory, file, pgvector and Qdrant, plus a plugin contract | 50+ integrations | Many integrations | Bring your own | | Agents | Query planning and iterative retrieval | Mature agent framework | Agents, workflows, memory | Tool calling and agent loops |

Choose LangChain.js for the widest integration catalogue, Mastra for agents and workflows with LLM-judge evals, and the AI SDK as the model layer; use this library for the retrieval, grounding and evaluation parts, on its own or under any of them. LlamaIndex.TS is deprecated (its repository is archived); see Coming from LlamaIndex.TS.

Connectors and plugins

| Connector | Embeddings | Generation | Notes | | -------------------- | :--------: | :--------: | -------------------------------------------------------------------------------------------------------------------- | | OpenAIConnector | ✓ | ✓ | OPENAI_API_KEY; baseURL for OpenAI-compatible APIs (Groq, Together, vLLM, LM Studio); needs npm install openai | | AnthropicConnector | | ✓ | ANTHROPIC_API_KEY | | CohereConnector | ✓ | | Embeddings and reranking, COHERE_API_KEY | | OllamaConnector | ✓ | ✓ | Local models, no key | | LocalEmbedder | ✓ | | Offline TF-IDF, fitted to your corpus |

PgVectorRetriever and QdrantRetriever store and search documents in PostgreSQL with pgvector and in Qdrant (vector stores); efSearch trades pgvector query speed for recall. Their ingest speed, query latency and recall, measured in CI, are on the Benchmarks page.

Vercel AI SDK models (any provider it supports) work as the embedder and LLM through createAiSdkAdapter; see Use with other frameworks.

Connectors read API keys when they are created, retry only transient failures (network errors, 429, 5xx) with backoff, and send retrieved documents to the model as clearly delimited, untrusted reference data rather than as instructions.

A plugin is any object with the method its stage needs: embed(), retrieve()/store(), generate(), rerank() or load(). Reference your own modules from .ragrc.json, or install packaged plugins with checksum verification and a static security scan:

npx rag-pipeline hub install ./my-llm-plugin        # also .tgz files, npm:<package> or a registry
npx rag-pipeline hub certify check ./my-llm-plugin   # scores contract, security, tests and docs

Experimental modules

Simulated or incomplete modules live under a separate entry point and are not covered by the stability guarantees in SEMVER.md: model training, federated learning, multimodal processing, adaptive retrieval, SSO providers, multi-tenancy, data governance, the plugin sandbox and the plugin certification class.

import { TenantManager } from "@devilsdev/rag-pipeline-utils/experimental";

They are exported only from /experimental, not from the main entry (2.x also exported them there, with a deprecation warning). Do not use them for authentication, tenant isolation or compliance. The Experimental modules page describes what each one really does.

Compatibility

| | | | -------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | Node.js | 22 and 24 | | Module formats | CommonJS (require) and ESM (import) | | TypeScript | Declarations for every export, including /experimental, compiled and run against the package in CI | | Versioning | Semantic versioning with a deprecation window, see SEMVER.md | | Supply chain | Published from GitHub Actions with npm provenance |

Documentation

Security

Report vulnerabilities privately as described in SECURITY.md. The security capability matrix lists what is hardened, what is recommended configuration, and what is an example only.

Contributing

Issues and pull requests are welcome. Start with the contributing guide, and use GitHub Discussions for questions and ideas. Run npm test and npm run lint before opening a pull request.

License

MIT