ultimate-mcp-server
Version:
The definitive all-in-one Model Context Protocol server for AI-assisted coding across 30+ platforms
117 lines • 3.95 kB
JavaScript
export class MemoryVectorStore {
name = 'memory';
dimension;
vectors = new Map();
embeddingProvider;
constructor(embeddingProvider) {
this.embeddingProvider = embeddingProvider;
this.dimension = embeddingProvider.dimension;
}
async addDocuments(documents) {
for (const doc of documents) {
const embedding = doc.embedding || await this.embeddingProvider.embed(doc.content);
this.vectors.set(doc.id, {
id: doc.id,
vector: embedding,
content: doc.content,
metadata: {
...doc.metadata,
type: 'document'
}
});
}
}
async addChunks(chunks) {
const embeddings = await this.embeddingProvider.embedBatch(chunks.map(chunk => chunk.content));
chunks.forEach((chunk, index) => {
this.vectors.set(chunk.id, {
id: chunk.id,
vector: embeddings[index],
content: chunk.content,
metadata: {
...chunk.metadata,
documentId: chunk.documentId,
type: 'chunk'
}
});
});
}
async search(query, options = {}) {
const { topK = 10, threshold = 0.0, filter, includeMetadata = true, includeEmbeddings = false } = options;
// Get query embedding
const queryVector = typeof query === 'string'
? await this.embeddingProvider.embed(query)
: query;
// Calculate similarities
const results = [];
for (const entry of this.vectors.values()) {
// Apply filters if provided
if (filter && !this.matchesFilter(entry.metadata, filter)) {
continue;
}
const score = this.cosineSimilarity(queryVector, entry.vector);
if (score >= threshold) {
results.push({ entry, score });
}
}
// Sort by score (descending) and take top K
results.sort((a, b) => b.score - a.score);
const topResults = results.slice(0, topK);
// Format results
return topResults.map(({ entry, score }) => ({
id: entry.id,
score,
content: entry.content,
metadata: includeMetadata ? entry.metadata : undefined,
embedding: includeEmbeddings ? entry.vector : undefined
}));
}
async delete(ids) {
for (const id of ids) {
this.vectors.delete(id);
}
}
async clear() {
this.vectors.clear();
}
cosineSimilarity(a, b) {
if (a.length !== b.length) {
throw new Error('Vectors must have the same dimension');
}
let dotProduct = 0;
let normA = 0;
let normB = 0;
for (let i = 0; i < a.length; i++) {
dotProduct += a[i] * b[i];
normA += a[i] * a[i];
normB += b[i] * b[i];
}
const similarity = dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
return similarity;
}
matchesFilter(metadata, filter) {
for (const [key, value] of Object.entries(filter)) {
if (Array.isArray(value)) {
if (!value.includes(metadata[key])) {
return false;
}
}
else if (metadata[key] !== value) {
return false;
}
}
return true;
}
// Additional utility methods
size() {
return this.vectors.size;
}
getStats() {
const count = this.vectors.size;
const dimensions = this.dimension;
// Rough estimate of memory usage
const memoryUsage = count * dimensions * 4; // 4 bytes per float
return { count, dimensions, memoryUsage };
}
}
//# sourceMappingURL=memory.js.map