Persistent semantic memory HTTP server for AI agents. No cloud, no API keys. Local vector index with Ollama/TF-IDF embeddings. Endpoints: /store, /recall, /forget, /list, /health
64 lines
1.8 KiB
JavaScript
64 lines
1.8 KiB
JavaScript
'use strict';
|
|
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const os = require('os');
|
|
const { randomUUID } = require('crypto');
|
|
const { LocalIndex } = require('vectra');
|
|
|
|
const STORE_DIR = path.join(os.homedir(), '.memory-bridge', 'index');
|
|
|
|
let index = null;
|
|
|
|
async function init() {
|
|
fs.mkdirSync(STORE_DIR, { recursive: true });
|
|
index = new LocalIndex(STORE_DIR);
|
|
if (!(await index.isIndexCreated())) {
|
|
await index.createIndex();
|
|
console.log(`Vector index : created at ${STORE_DIR}`);
|
|
} else {
|
|
console.log(`Vector index : loaded from ${STORE_DIR}`);
|
|
}
|
|
}
|
|
|
|
async function add({ text, tags = [], source = '', vector }) {
|
|
const id = randomUUID();
|
|
const createdAt = new Date().toISOString();
|
|
await index.insertItem({ id, vector, metadata: { id, text, tags, source, createdAt } });
|
|
return { id, createdAt };
|
|
}
|
|
|
|
async function query({ vector, limit = 10, tags = [] }) {
|
|
const topK = tags.length ? Math.min(limit * 3, 300) : limit;
|
|
const results = await index.queryItems(vector, topK);
|
|
let items = results;
|
|
if (tags.length) {
|
|
items = results.filter((r) =>
|
|
tags.some((t) => (r.item.metadata.tags || []).includes(t))
|
|
);
|
|
}
|
|
return items.slice(0, limit).map((r) => ({
|
|
...r.item.metadata,
|
|
score: r.score,
|
|
}));
|
|
}
|
|
|
|
async function remove(id) {
|
|
await index.deleteItem(id);
|
|
}
|
|
|
|
async function list({ page = 1, pageSize = 50 } = {}) {
|
|
const all = await index.listItems();
|
|
const total = all.length;
|
|
const start = (page - 1) * pageSize;
|
|
const data = all.slice(start, start + pageSize).map((item) => item.metadata);
|
|
return { data, total, page, pageSize, pages: Math.ceil(total / pageSize) };
|
|
}
|
|
|
|
async function count() {
|
|
const all = await index.listItems();
|
|
return all.length;
|
|
}
|
|
|
|
module.exports = { init, add, query, remove, list, count };
|