import fs from "node:fs"; import path from "node:path"; export type IdentityEntry = { discordUserId: string; agentId: string; agentName: string; }; export class IdentityRegistry { private filePath: string; private entries: IdentityEntry[] = []; private loaded = false; constructor(filePath: string) { this.filePath = filePath; } private load(): void { if (this.loaded) return; this.loaded = true; if (!fs.existsSync(this.filePath)) { this.entries = []; return; } try { const raw = fs.readFileSync(this.filePath, "utf8"); const parsed = JSON.parse(raw); this.entries = Array.isArray(parsed) ? parsed : []; } catch { this.entries = []; } } private save(): void { const dir = path.dirname(this.filePath); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); fs.writeFileSync(this.filePath, JSON.stringify(this.entries, null, 2), "utf8"); } upsert(entry: IdentityEntry): void { this.load(); const idx = this.entries.findIndex((e) => e.agentId === entry.agentId); if (idx >= 0) { this.entries[idx] = entry; } else { this.entries.push(entry); } this.save(); } remove(agentId: string): boolean { this.load(); const before = this.entries.length; this.entries = this.entries.filter((e) => e.agentId !== agentId); if (this.entries.length !== before) { this.save(); return true; } return false; } findByAgentId(agentId: string): IdentityEntry | undefined { this.load(); return this.entries.find((e) => e.agentId === agentId); } findByDiscordUserId(discordUserId: string): IdentityEntry | undefined { this.load(); return this.entries.find((e) => e.discordUserId === discordUserId); } list(): IdentityEntry[] { this.load(); return [...this.entries]; } /** Build a map from discordUserId → agentId for fast lookup. */ buildDiscordToAgentMap(): Map { this.load(); const map = new Map(); for (const e of this.entries) map.set(e.discordUserId, e.agentId); return map; } /** Build a map from agentId → discordUserId for fast lookup. */ buildAgentToDiscordMap(): Map { this.load(); const map = new Map(); for (const e of this.entries) map.set(e.agentId, e.discordUserId); return map; } }