arela
Version:
AI-powered CTO with multi-agent orchestration, code summarization, visual testing (web + mobile) for blazing fast development.
67 lines • 2.08 kB
JavaScript
import path from "node:path";
import fs from "fs-extra";
import { buildIndex, search } from "../rag/index.js";
const DEFAULT_TOP_K = 5;
export class VectorMemory {
cwd;
constructor(cwd = process.cwd()) {
this.cwd = cwd;
}
get indexPath() {
return path.join(this.cwd, ".arela", ".rag-index.json");
}
async isReady() {
return fs.pathExists(this.indexPath);
}
async getStats() {
if (!(await this.isReady())) {
return {
ready: false,
filesIndexed: 0,
embeddings: 0,
indexPath: this.indexPath,
};
}
const index = await fs.readJson(this.indexPath);
const files = new Set();
for (const embedding of index.embeddings ?? []) {
if (embedding.file) {
files.add(embedding.file);
}
}
return {
ready: true,
filesIndexed: files.size,
embeddings: index.embeddings?.length ?? 0,
model: index.model,
lastIndexedAt: index.timestamp,
indexPath: this.indexPath,
};
}
async rebuildIndex(options) {
await buildIndex({
cwd: this.cwd,
...(options ?? {}),
});
return this.getStats();
}
async query(question, topK = DEFAULT_TOP_K) {
if (!(await this.isReady())) {
throw new Error("Vector memory is not initialized. Run `arela index` or `arela memory init --refresh-vector` first.");
}
const results = await search(question, { cwd: this.cwd }, topK);
return results.map((item) => ({
file: item.file,
snippet: summarizeSnippet(item.chunk),
score: Number(item.score?.toFixed(4) ?? 0),
}));
}
}
function summarizeSnippet(chunk) {
const normalized = chunk.replace(/\s+/g, " ").trim();
if (normalized.length <= 160) {
return normalized;
}
return `${normalized.slice(0, 157)}...`;
}
//# sourceMappingURL=vector.js.map