refactor: make root path for configurations
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
SUPERMEMORY_API_KEY=
|
SUPERMEMORY_API_KEY=
|
||||||
|
|
||||||
BRAINDB_PATH=./braindb.json
|
BRAINBOX_ROOT_PATH=./brainbox-data
|
||||||
|
|
||||||
OPENROUTER_API_KEY=
|
OPENROUTER_API_KEY=
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -27,6 +27,9 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
|||||||
.cache
|
.cache
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# brainbox data
|
||||||
|
brainbox-data/
|
||||||
|
|
||||||
# IntelliJ based IDEs
|
# IntelliJ based IDEs
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { config } from "@/config";
|
import { config } from "@/config";
|
||||||
import { readFile, writeFile } from "fs/promises";
|
import { mkdir, readFile, rm, writeFile } from "fs/promises";
|
||||||
|
import { join } from "path";
|
||||||
|
|
||||||
export interface BrainItem {
|
export interface BrainItem {
|
||||||
brainId: string;
|
brainId: string;
|
||||||
@@ -7,51 +8,90 @@ export interface BrainItem {
|
|||||||
displayName: string;
|
displayName: string;
|
||||||
baseSystemPrompt: string;
|
baseSystemPrompt: string;
|
||||||
}
|
}
|
||||||
export type BrainDB = Record<string, BrainItem>;
|
export type BrainList = BrainItem[];
|
||||||
|
|
||||||
|
// Layout:
|
||||||
|
// <root>/brains.json — BrainItem[] index, mirror
|
||||||
|
// <root>/<brainId>/brain.json — BrainItem per brain, source of truth
|
||||||
|
|
||||||
export class BrainDBManager {
|
export class BrainDBManager {
|
||||||
constructor(private readonly braindbPath: string = config.braindbPath) {}
|
constructor(private readonly root: string = config.brainboxRoot) {}
|
||||||
|
|
||||||
private get db() {
|
private brainDir(brainId: string): string {
|
||||||
return readFile(this.braindbPath, { encoding: "utf-8" }).then(
|
return join(this.root, brainId);
|
||||||
(content) => {
|
}
|
||||||
return JSON.parse(content) as BrainDB;
|
|
||||||
},
|
private brainFile(brainId: string): string {
|
||||||
|
return join(this.brainDir(brainId), "brain.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
private indexFile(): string {
|
||||||
|
return join(this.root, "brains.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async readIndex(): Promise<BrainList> {
|
||||||
|
try {
|
||||||
|
const content = await readFile(this.indexFile(), { encoding: "utf-8" });
|
||||||
|
return JSON.parse(content) as BrainList;
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async writeIndex(list: BrainList): Promise<void> {
|
||||||
|
await mkdir(this.root, { recursive: true });
|
||||||
|
await writeFile(
|
||||||
|
this.indexFile(),
|
||||||
|
JSON.stringify(list, null, 2),
|
||||||
|
{ encoding: "utf-8" },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async writeDb(db: BrainDB) {
|
private async writeBrain(brain: BrainItem): Promise<void> {
|
||||||
await writeFile(this.braindbPath, JSON.stringify(db), {
|
await mkdir(this.brainDir(brain.brainId), { recursive: true });
|
||||||
encoding: "utf-8",
|
await writeFile(
|
||||||
});
|
this.brainFile(brain.brainId),
|
||||||
|
JSON.stringify(brain, null, 2),
|
||||||
|
{ encoding: "utf-8" },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadBrain(brainId: string): Promise<BrainItem | undefined> {
|
async loadBrain(brainId: string): Promise<BrainItem | undefined> {
|
||||||
const brainOrNot = (await this.db)[brainId];
|
try {
|
||||||
return brainOrNot;
|
const content = await readFile(this.brainFile(brainId), {
|
||||||
|
encoding: "utf-8",
|
||||||
|
});
|
||||||
|
return JSON.parse(content) as BrainItem;
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveBrain(brainId: string, brain: BrainItem) {
|
async saveBrain(brainId: string, brain: BrainItem): Promise<void> {
|
||||||
const db = await this.db;
|
await this.writeBrain(brain);
|
||||||
db[brainId] = brain;
|
const list = await this.readIndex();
|
||||||
await this.writeDb(db);
|
const idx = list.findIndex((b) => b.brainId === brainId);
|
||||||
|
if (idx >= 0) list[idx] = brain;
|
||||||
|
else list.push(brain);
|
||||||
|
await this.writeIndex(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
async listBrain() {
|
async listBrain(): Promise<Array<{ brainId: string; displayName: string }>> {
|
||||||
return Object.entries(await this.db).map(
|
const list = await this.readIndex();
|
||||||
([_, { brainId, displayName }]) => ({ brainId, displayName }),
|
return list.map(({ brainId, displayName }) => ({ brainId, displayName }));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBrain(brainId: string) {
|
async deleteBrain(brainId: string): Promise<void> {
|
||||||
const db = await this.db;
|
await rm(this.brainDir(brainId), { recursive: true, force: true });
|
||||||
delete db[brainId];
|
const list = await this.readIndex();
|
||||||
await this.writeDb(db);
|
const filtered = list.filter((b) => b.brainId !== brainId);
|
||||||
|
if (filtered.length === list.length) return;
|
||||||
|
await this.writeIndex(filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
async isBrainAvailable(brainId: string) {
|
async isBrainAvailable(brainId: string): Promise<boolean> {
|
||||||
return brainId in (await this.db);
|
return (await this.loadBrain(brainId)) !== undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const brainManager = new BrainDBManager();
|
export const brainManager = new BrainDBManager();
|
||||||
@@ -4,7 +4,7 @@ import { join } from "path";
|
|||||||
export interface Config {
|
export interface Config {
|
||||||
openrouterApiKey: string;
|
openrouterApiKey: string;
|
||||||
supermemoryApiKey: string;
|
supermemoryApiKey: string;
|
||||||
braindbPath: string;
|
brainboxRoot: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const openrouterApiKey = process.env["OPENROUTER_API_KEY"];
|
const openrouterApiKey = process.env["OPENROUTER_API_KEY"];
|
||||||
@@ -13,13 +13,13 @@ if (!openrouterApiKey) throw new Error("OPENROUTER_API_KEY is missing");
|
|||||||
const supermemoryApiKey = process.env["SUPERMEMORY_API_KEY"];
|
const supermemoryApiKey = process.env["SUPERMEMORY_API_KEY"];
|
||||||
if (!supermemoryApiKey) throw new Error("SUPERMEMORY_API_KEY is missing");
|
if (!supermemoryApiKey) throw new Error("SUPERMEMORY_API_KEY is missing");
|
||||||
|
|
||||||
const braindbPath = join(
|
const brainboxRoot = join(
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
process.env["BRAINDB_PATH"] ?? "brainbox.json",
|
process.env["BRAINBOX_ROOT_PATH"] ?? "brainbox-data",
|
||||||
);
|
);
|
||||||
|
|
||||||
export const config: Config = {
|
export const config: Config = {
|
||||||
openrouterApiKey,
|
openrouterApiKey,
|
||||||
supermemoryApiKey,
|
supermemoryApiKey,
|
||||||
braindbPath,
|
brainboxRoot,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user