
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@vibe-agent-toolkit/rag
Advanced tools
Abstract RAG (Retrieval-Augmented Generation) interfaces and shared implementations
Abstract RAG (Retrieval-Augmented Generation) interfaces and shared implementations for vibe-agent-toolkit.
This package provides the core interfaces and schemas for RAG functionality in VAT (Vibe Agent Toolkit). It defines contracts that RAG implementations must follow, ensuring portability and consistency across different vector database backends.
What's included:
RAGQueryProvider, RAGAdminProvider, EmbeddingProvider, TokenCounterFastTokenCounter (bytes/4 heuristic), ApproximateTokenCounter (gpt-tokenizer)TransformersEmbeddingProvider (local, transformers.js), OpenAIEmbeddingProvider (cloud, OpenAI API)What's NOT included:
@vibe-agent-toolkit/rag-lancedb)By default, RAG chunks include sensible metadata fields optimized for markdown documentation (filePath, tags, type, headingPath, etc.). You can extend or completely replace these defaults with your own custom metadata.
RAG chunks are composed of two parts:
The default RAGChunk type is CoreRAGChunk & DefaultRAGMetadata.
Use Zod to define your custom metadata schema:
import { z } from 'zod';
import {
createCustomRAGChunkSchema,
CoreRAGChunkSchema,
DefaultRAGMetadataSchema,
} from '@vibe-agent-toolkit/rag';
// Option 1: Extend default metadata
const ExtendedMetadataSchema = DefaultRAGMetadataSchema.extend({
domain: z.string(),
priority: z.number().optional(),
});
// Option 2: Replace with custom metadata
const CustomMetadataSchema = z.object({
sourceUrl: z.string(),
domain: z.string(),
category: z.string().optional(),
keywords: z.array(z.string()),
});
// Create chunk schema
const CustomChunkSchema = createCustomRAGChunkSchema(CustomMetadataSchema);
type CustomChunk = z.infer<typeof CustomChunkSchema>;
TypeScript automatically infers types from your Zod schema:
const chunk: CustomChunk = {
// Core fields (required)
chunkId: 'chunk-1',
resourceId: 'doc-1',
content: 'Authentication guide',
contentHash: 'abc123',
tokenCount: 50,
embedding: [0.1, 0.2, 0.3],
embeddingModel: 'text-embedding-3-small',
embeddedAt: new Date(),
// Custom metadata fields
sourceUrl: 'https://example.com/docs/auth.md',
domain: 'security',
keywords: ['auth', 'oauth', 'jwt'],
};
See the LanceDB provider documentation for usage with databases.
bun add @vibe-agent-toolkit/rag
@vibe-agent-toolkit/rag - This package (interfaces + shared implementations)@vibe-agent-toolkit/rag-lancedb - LanceDB implementation@vibe-agent-toolkit/rag-pinecone, @vibe-agent-toolkit/rag-weaviate, etc.import type { RAGQueryProvider, RAGQuery } from '@vibe-agent-toolkit/rag';
// Get a RAG provider implementation (from rag-lancedb or other package)
const rag: RAGQueryProvider = ...; // Implementation
// Query the RAG database
const result = await rag.query({
text: 'How do I validate schemas?',
limit: 5,
filters: {
tags: ['validation'],
type: 'documentation'
}
});
// Use results
for (const chunk of result.chunks) {
console.log(`[${chunk.headingPath}] ${chunk.content}`);
}
import { RAGQuerySchema, RAGChunkSchema } from '@vibe-agent-toolkit/rag';
// Validate a query
const queryResult = RAGQuerySchema.safeParse(userInput);
if (!queryResult.success) {
console.error('Invalid query:', queryResult.error);
}
// Validate a chunk
const chunkResult = RAGChunkSchema.safeParse(data);
if (chunkResult.success) {
const chunk = chunkResult.data; // Typed as RAGChunk
}
import { jsonSchemas } from '@vibe-agent-toolkit/rag';
// Get JSON Schema for RAGChunk
const schema = jsonSchemas.RAGChunk;
// Use for documentation, validation, code generation, etc.
console.log(JSON.stringify(schema, null, 2));
Token counters are used for accurate chunking and embedding token limit management.
Fast but inaccurate token estimation using bytes/4 heuristic.
import { FastTokenCounter } from '@vibe-agent-toolkit/rag';
const counter = new FastTokenCounter();
const tokens = counter.count('Hello world'); // ~3 tokens (bytes/4)
Characteristics:
Accurate token counting using gpt-tokenizer library.
import { ApproximateTokenCounter } from '@vibe-agent-toolkit/rag';
const counter = new ApproximateTokenCounter();
const tokens = counter.count('Hello world'); // 2 tokens (accurate)
Characteristics:
| Counter | Speed | Accuracy | Padding Factor | Use Case |
|---|---|---|---|---|
| FastTokenCounter | Very Fast | ~75% | 0.8 | Quick estimation |
| ApproximateTokenCounter | Fast | ~95% | 0.9 | RAG chunking |
The padding factor provides a safety margin to avoid exceeding embedding model token limits:
const targetChunkSize = 512; // tokens
const paddingFactor = 0.9; // 90%
const effectiveTarget = targetChunkSize * paddingFactor; // 460 tokens
// Chunk to effective target to avoid splits from estimation error
Why padding matters:
Embedding providers convert text to vector embeddings for semantic search.
Local embedding generation using transformers.js - no API key required.
import { TransformersEmbeddingProvider } from '@vibe-agent-toolkit/rag';
const provider = new TransformersEmbeddingProvider();
// Default model: Xenova/all-MiniLM-L6-v2 (384 dimensions)
const embedding = await provider.embed('Search query text');
console.log(embedding.length); // 384
// Batch embedding for efficiency
const embeddings = await provider.embedBatch(['text1', 'text2', 'text3']);
Characteristics:
First run: Downloads model (~20MB for all-MiniLM-L6-v2)
Cloud-based embedding using OpenAI API - requires API key.
import { OpenAIEmbeddingProvider } from '@vibe-agent-toolkit/rag';
const provider = new OpenAIEmbeddingProvider({
apiKey: process.env.OPENAI_API_KEY!,
model: 'text-embedding-3-small', // or 'text-embedding-3-large'
});
const embedding = await provider.embed('Search query text');
console.log(embedding.length); // 1536
// Custom dimensions (text-embedding-3-* models only)
const customProvider = new OpenAIEmbeddingProvider({
apiKey: process.env.OPENAI_API_KEY!,
model: 'text-embedding-3-small',
dimensions: 512, // Reduce dimensions for faster search
});
Characteristics:
Installation: bun add openai (optional dependency)
| Provider | Speed | Quality | Cost | Dimensions | Use Case |
|---|---|---|---|---|---|
| TransformersEmbeddingProvider | Fast | Good | Free | 384 | Default choice |
| OpenAIEmbeddingProvider | Medium | Excellent | Paid | 1536-3072 | Production, high quality |
Use TransformersEmbeddingProvider when:
Use OpenAIEmbeddingProvider when:
Chunking utilities split documents into semantic chunks for embedding and retrieval.
Hybrid Approach:
import { chunkResource, enrichChunks } from '@vibe-agent-toolkit/rag';
import { ApproximateTokenCounter } from '@vibe-agent-toolkit/rag';
import { ResourceRegistry } from '@vibe-agent-toolkit/resources';
// 1. Get resource from ResourceRegistry
const registry = new ResourceRegistry();
await registry.crawl({ baseDir: './docs' });
const metadata = registry.getResourceById('resource-id');
// 2. Read file content and parse frontmatter (not included in ResourceMetadata)
const content = await fs.readFile(metadata.filePath, 'utf-8');
const frontmatter = /* parse frontmatter */;
const resource = { ...metadata, content, frontmatter };
// 3. Configure chunking
const config = {
targetChunkSize: 512, // Ideal chunk size
modelTokenLimit: 8191, // Hard limit (embedding model)
paddingFactor: 0.9, // 90% of target (safety margin)
tokenCounter: new ApproximateTokenCounter(),
};
// 4. Chunk the resource
const result = chunkResource(resource, config);
console.log(`Created ${result.stats.totalChunks} chunks`);
console.log(`Average tokens: ${result.stats.averageTokens}`);
// 5. Enrich with embeddings (after embedding)
const embeddings = await embeddingProvider.embedBatch(
result.chunks.map(c => c.content)
);
const ragChunks = enrichChunks(
result.chunks,
resource,
embeddings,
'text-embedding-3-small'
);
| Option | Description | Example |
|---|---|---|
targetChunkSize | Ideal chunk size in tokens | 512 |
modelTokenLimit | Hard limit (embedding model) | 8191 (OpenAI) |
paddingFactor | Safety margin (0.8-1.0) | 0.9 (ApproximateTokenCounter) |
tokenCounter | Token counter to use | ApproximateTokenCounter |
minChunkSize | Minimum chunk size (optional) | 50 |
See Token Counters for padding factor recommendations:
Lower accuracy = lower padding factor (more safety margin)
import {
chunkByTokens,
splitByParagraphs,
splitBySentences,
generateContentHash,
generateChunkId,
calculateEffectiveTarget,
} from '@vibe-agent-toolkit/rag';
// Split text by token count
const chunks = chunkByTokens('long text...', config);
// Split by paragraphs
const paragraphs = splitByParagraphs(text);
// Generate content hash for change detection
const hash = generateContentHash(content);
// Calculate effective target with padding
const effectiveTarget = calculateEffectiveTarget(512, 0.9); // 460
Read-only provider interface for querying RAG databases.
interface RAGQueryProvider {
query(query: RAGQuery): Promise<RAGResult>;
getStats(): Promise<RAGStats>;
}
Read/write provider interface for building and managing RAG databases.
interface RAGAdminProvider extends RAGQueryProvider {
indexResources(resources: ResourceMetadata[]): Promise<IndexResult>;
updateResource(resourceId: string): Promise<void>;
deleteResource(resourceId: string): Promise<void>;
clear(): Promise<void>;
close(): Promise<void>;
}
Interface for embedding providers (transformers.js, OpenAI, etc.)
interface EmbeddingProvider {
name: string;
model: string;
dimensions: number;
embed(text: string): Promise<number[]>;
embedBatch(texts: string[]): Promise<number[][]>;
}
Interface for token counting implementations.
interface TokenCounter {
name: string;
count(text: string): number;
countBatch(texts: string[]): number[];
}
All schemas are defined with Zod and exported as both TypeScript types and JSON Schemas.
RAGChunkSchema / RAGChunk - Structure of a chunk in the RAG databaseRAGQuerySchema / RAGQuery - Structure of a queryRAGResultSchema / RAGResult - Structure of query resultsRAGStatsSchema / RAGStats - Database statisticsIndexResultSchema / IndexResult - Result from indexing operationKey principles:
# Build
bun run build
# Test
bun run test:unit
# Type check
bun run typecheck
MIT
FAQs
Abstract RAG (Retrieval-Augmented Generation) interfaces and shared implementations
We found that @vibe-agent-toolkit/rag demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.