fix: scan full cortex history for conversation matches
This commit is contained in:
parent
bb27f35319
commit
a2b0d03cbb
@ -86,4 +86,47 @@ describe("cortex capture history", () => {
|
||||
expect(syncEntry?.timestamp).toBe(2_000);
|
||||
expect(syncEntry?.syncPlatforms).toEqual(["claude-code", "cursor", "copilot"]);
|
||||
});
|
||||
|
||||
it("finds an older matching conversation entry even when newer unrelated entries exceed 100", async () => {
|
||||
const stateDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-cortex-history-scan-"));
|
||||
vi.stubEnv("OPENCLAW_STATE_DIR", stateDir);
|
||||
|
||||
await appendCortexCaptureHistory({
|
||||
agentId: "main",
|
||||
sessionId: "session-target",
|
||||
channelId: "channel-target",
|
||||
captured: true,
|
||||
score: 0.8,
|
||||
reason: "target conversation capture",
|
||||
timestamp: 1_000,
|
||||
});
|
||||
|
||||
for (let index = 0; index < 150; index += 1) {
|
||||
await appendCortexCaptureHistory({
|
||||
agentId: "main",
|
||||
sessionId: `session-${index}`,
|
||||
channelId: `channel-${index}`,
|
||||
captured: true,
|
||||
score: 0.5,
|
||||
reason: `other capture ${index}`,
|
||||
timestamp: 2_000 + index,
|
||||
});
|
||||
}
|
||||
|
||||
const asyncEntry = await getLatestCortexCaptureHistoryEntry({
|
||||
agentId: "main",
|
||||
sessionId: "session-target",
|
||||
channelId: "channel-target",
|
||||
});
|
||||
const syncEntry = getLatestCortexCaptureHistoryEntrySync({
|
||||
agentId: "main",
|
||||
sessionId: "session-target",
|
||||
channelId: "channel-target",
|
||||
});
|
||||
|
||||
expect(asyncEntry?.reason).toBe("target conversation capture");
|
||||
expect(asyncEntry?.timestamp).toBe(1_000);
|
||||
expect(syncEntry?.reason).toBe("target conversation capture");
|
||||
expect(syncEntry?.timestamp).toBe(1_000);
|
||||
});
|
||||
});
|
||||
|
||||
@ -18,6 +18,50 @@ export type CortexCaptureHistoryEntry = {
|
||||
|
||||
const latestCortexCaptureHistoryByKey = new Map<string, CortexCaptureHistoryEntry>();
|
||||
|
||||
function matchesHistoryEntry(
|
||||
entry: CortexCaptureHistoryEntry,
|
||||
params: {
|
||||
agentId: string;
|
||||
sessionId?: string;
|
||||
channelId?: string;
|
||||
},
|
||||
): boolean {
|
||||
return (
|
||||
entry.agentId === params.agentId &&
|
||||
(params.sessionId ? entry.sessionId === params.sessionId : true) &&
|
||||
(params.channelId ? entry.channelId === params.channelId : true)
|
||||
);
|
||||
}
|
||||
|
||||
function parseLatestMatchingHistoryEntry(
|
||||
raw: string,
|
||||
params: {
|
||||
agentId: string;
|
||||
sessionId?: string;
|
||||
channelId?: string;
|
||||
},
|
||||
): CortexCaptureHistoryEntry | 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 (matchesHistoryEntry(entry, params)) {
|
||||
return entry;
|
||||
}
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function buildHistoryCacheKey(params: {
|
||||
agentId: string;
|
||||
sessionId?: string;
|
||||
@ -91,29 +135,7 @@ export function getLatestCortexCaptureHistoryEntrySync(params: {
|
||||
} 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;
|
||||
return parseLatestMatchingHistoryEntry(raw, params);
|
||||
}
|
||||
|
||||
export function getCachedLatestCortexCaptureHistoryEntry(params: {
|
||||
@ -138,14 +160,14 @@ export async function getLatestCortexCaptureHistoryEntry(params: {
|
||||
channelId?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}): Promise<CortexCaptureHistoryEntry | null> {
|
||||
const recent = await readRecentCortexCaptureHistory({ limit: 100, env: params.env });
|
||||
const match =
|
||||
recent.find(
|
||||
(entry) =>
|
||||
entry.agentId === params.agentId &&
|
||||
(params.sessionId ? entry.sessionId === params.sessionId : true) &&
|
||||
(params.channelId ? entry.channelId === params.channelId : true),
|
||||
) ?? null;
|
||||
const historyPath = resolveHistoryPath(params.env);
|
||||
let raw: string;
|
||||
try {
|
||||
raw = await fsp.readFile(historyPath, "utf8");
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
const match = parseLatestMatchingHistoryEntry(raw, params);
|
||||
if (match) {
|
||||
cacheHistoryEntry(match);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user