feat: integrate Cortex local memory into OpenClaw
This commit is contained in:
parent
a5e9461b26
commit
0f03c4d256
112
src/agents/cortex-history.ts
Normal file
112
src/agents/cortex-history.ts
Normal file
@ -0,0 +1,112 @@
|
||||
import fs from "node:fs";
|
||||
import fsp from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
|
||||
export type CortexCaptureHistoryEntry = {
|
||||
agentId: string;
|
||||
sessionId?: string;
|
||||
channelId?: string;
|
||||
captured: boolean;
|
||||
score: number;
|
||||
reason: string;
|
||||
error?: string;
|
||||
syncedCodingContext?: boolean;
|
||||
syncPlatforms?: string[];
|
||||
timestamp: number;
|
||||
};
|
||||
|
||||
function resolveHistoryPath(env: NodeJS.ProcessEnv = process.env): string {
|
||||
return path.join(resolveStateDir(env), "logs", "cortex-memory-captures.jsonl");
|
||||
}
|
||||
|
||||
export async function appendCortexCaptureHistory(
|
||||
entry: CortexCaptureHistoryEntry,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): Promise<void> {
|
||||
const historyPath = resolveHistoryPath(env);
|
||||
await fsp.mkdir(path.dirname(historyPath), { recursive: true });
|
||||
await fsp.appendFile(historyPath, `${JSON.stringify(entry)}\n`, "utf8");
|
||||
}
|
||||
|
||||
export async function readRecentCortexCaptureHistory(params?: {
|
||||
limit?: number;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}): Promise<CortexCaptureHistoryEntry[]> {
|
||||
const historyPath = resolveHistoryPath(params?.env);
|
||||
let raw: string;
|
||||
try {
|
||||
raw = await fsp.readFile(historyPath, "utf8");
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
const parsed = raw
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean)
|
||||
.map((line) => {
|
||||
try {
|
||||
return JSON.parse(line) as CortexCaptureHistoryEntry;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter((entry): entry is CortexCaptureHistoryEntry => entry != null);
|
||||
const limit = Math.max(1, params?.limit ?? 20);
|
||||
return parsed.slice(-limit).toReversed();
|
||||
}
|
||||
|
||||
export function getLatestCortexCaptureHistoryEntrySync(params: {
|
||||
agentId: string;
|
||||
sessionId?: string;
|
||||
channelId?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}): CortexCaptureHistoryEntry | null {
|
||||
const historyPath = resolveHistoryPath(params.env);
|
||||
let raw: string;
|
||||
try {
|
||||
raw = fs.readFileSync(historyPath, "utf8");
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
const lines = raw
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean);
|
||||
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
||||
const line = lines[index];
|
||||
if (!line) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const entry = JSON.parse(line) as CortexCaptureHistoryEntry;
|
||||
if (
|
||||
entry.agentId === params.agentId &&
|
||||
(params.sessionId ? entry.sessionId === params.sessionId : true) &&
|
||||
(params.channelId ? entry.channelId === params.channelId : true)
|
||||
) {
|
||||
return entry;
|
||||
}
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function getLatestCortexCaptureHistoryEntry(params: {
|
||||
agentId: string;
|
||||
sessionId?: string;
|
||||
channelId?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}): Promise<CortexCaptureHistoryEntry | null> {
|
||||
const recent = await readRecentCortexCaptureHistory({ limit: 100, env: params.env });
|
||||
return (
|
||||
recent.find(
|
||||
(entry) =>
|
||||
entry.agentId === params.agentId &&
|
||||
(params.sessionId ? entry.sessionId === params.sessionId : true) &&
|
||||
(params.channelId ? entry.channelId === params.channelId : true),
|
||||
) ?? null
|
||||
);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user