feat: init Agent-Memory

This commit is contained in:
chrishuan
2026-04-09 18:23:46 +08:00
commit 7a5fce9f12
39 changed files with 13488 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
import { randomUUID } from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
export const REPORT_CONST = {
PLUGIN: "plugin",
} as const;
export type ReportPayload = Record<string, unknown>;
export interface IReporter {
reportFunc(category: string, payload: ReportPayload): void;
}
// ── Singleton ──
let _reporter: IReporter | undefined;
export function initReporter(opts: {
enabled: boolean;
type: string;
logger: { info: (msg: string) => void };
instanceId: string;
pluginVersion: string;
}): void {
if (_reporter) return;
if (!opts.enabled) return;
switch (opts.type) {
case "local":
_reporter = new LocalReporter(opts.logger, opts.instanceId, opts.pluginVersion);
break;
// TODO: add new reporter type
default:
opts.logger.info(`[memory-tdai] Unknown reporter type "${opts.type}", disabled reporting`);
break;
}
}
export function setReporter(reporter: IReporter): void {
_reporter = reporter;
}
export function report(event: string, data: ReportPayload): void {
if (!_reporter) return;
try {
_reporter.reportFunc(REPORT_CONST.PLUGIN, { event, ...data });
} catch { /* never block business logic */ }
}
// ── LocalReporter (default) ──
class LocalReporter implements IReporter {
constructor(
private readonly logger: { info: (msg: string) => void },
private readonly instanceId: string,
private readonly pluginVersion: string,
) {}
reportFunc(category: string, payload: ReportPayload): void {
try {
this.logger.info(JSON.stringify({
tag: "METRIC",
category,
plugin: "memory-tdai",
instanceId: this.instanceId,
pluginVersion: this.pluginVersion,
ts: new Date().toISOString(),
...payload,
}));
} catch { /* swallow */ }
}
}
// ── Instance ID (persisted per-install) ──
let _instanceIdCache: string | undefined;
export async function getOrCreateInstanceId(pluginDataDir: string): Promise<string> {
if (_instanceIdCache) return _instanceIdCache;
const idFile = path.join(pluginDataDir, ".metadata", "instance_id");
try {
const existing = (await fs.readFile(idFile, "utf-8")).trim();
if (existing) {
_instanceIdCache = existing;
return existing;
}
} catch { /* file doesn't exist */ }
const newId = randomUUID();
await fs.mkdir(path.dirname(idFile), { recursive: true });
await fs.writeFile(idFile, newId, "utf-8");
_instanceIdCache = newId;
return newId;
}