mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-28 06:59:56 +00:00
fix: honor active memory transcript privacy
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { appendSqliteSessionTranscriptEvent } from "openclaw/plugin-sdk/agent-harness-runtime";
|
||||
import {
|
||||
appendSqliteSessionTranscriptEvent,
|
||||
hasSqliteSessionTranscriptEvents,
|
||||
} from "openclaw/plugin-sdk/agent-harness-runtime";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { resetPluginStateStoreForTests } from "openclaw/plugin-sdk/plugin-state-runtime";
|
||||
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
|
||||
@@ -4052,11 +4055,21 @@ describe("active-memory plugin", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps subagent transcripts in sqlite by default", async () => {
|
||||
it("deletes subagent transcripts by default after reading sqlite recall output", async () => {
|
||||
const mkdtempSpy = vi.spyOn(fs, "mkdtemp");
|
||||
const rmSpy = vi.spyOn(fs, "rm");
|
||||
let transcriptScope: TranscriptScope | undefined;
|
||||
runEmbeddedPiAgent.mockImplementationOnce(
|
||||
async (params: { agentId?: string; sessionId: string }) => {
|
||||
transcriptScope = transcriptScopeFromRunParams(params);
|
||||
await writeSqliteTranscriptEvents(transcriptScope, [
|
||||
{ type: "message", message: { role: "assistant", content: "private recall summary" } },
|
||||
]);
|
||||
return { payloads: [{ text: "private recall summary" }] };
|
||||
},
|
||||
);
|
||||
|
||||
await hooks.before_prompt_build(
|
||||
const result = await hooks.before_prompt_build(
|
||||
{ prompt: "what wings should i order? sqlite transcript scope", messages: [] },
|
||||
{
|
||||
agentId: "main",
|
||||
@@ -4066,11 +4079,16 @@ describe("active-memory plugin", () => {
|
||||
},
|
||||
);
|
||||
|
||||
expect(result).toMatchObject({
|
||||
prependContext: expect.stringContaining("private recall summary"),
|
||||
});
|
||||
const runParams = runEmbeddedPiAgent.mock.calls.at(-1)?.[0];
|
||||
expect(runParams).toMatchObject({
|
||||
agentId: "main",
|
||||
sessionId: expect.stringMatching(/^active-memory-[a-z0-9]+-[a-f0-9]{8}$/),
|
||||
});
|
||||
expect(transcriptScope).toBeDefined();
|
||||
expect(hasSqliteSessionTranscriptEvents(transcriptScope as TranscriptScope)).toBe(false);
|
||||
expect(mkdtempSpy).not.toHaveBeenCalled();
|
||||
expect(rmSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import crypto from "node:crypto";
|
||||
import { loadSqliteSessionTranscriptBoundedEvents } from "openclaw/plugin-sdk/agent-harness-runtime";
|
||||
import {
|
||||
deleteSqliteSessionTranscript,
|
||||
loadSqliteSessionTranscriptBoundedEvents,
|
||||
} from "openclaw/plugin-sdk/agent-harness-runtime";
|
||||
import {
|
||||
DEFAULT_PROVIDER,
|
||||
parseModelRef,
|
||||
@@ -1558,6 +1561,17 @@ async function streamBoundedTranscriptEvents(params: {
|
||||
}
|
||||
}
|
||||
|
||||
function deleteTransientRecallTranscript(transcriptScope: TranscriptScope | undefined): void {
|
||||
if (!transcriptScope) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
deleteSqliteSessionTranscript(transcriptScope);
|
||||
} catch {
|
||||
// Best-effort cleanup; recall results should not fail because transcript cleanup did.
|
||||
}
|
||||
}
|
||||
|
||||
function extractActiveMemorySearchDebugFromSessionRecord(
|
||||
value: unknown,
|
||||
): ActiveMemorySearchDebug | undefined {
|
||||
@@ -2568,8 +2582,9 @@ async function maybeResolveActiveRecall(params: {
|
||||
});
|
||||
|
||||
let terminalMemorySearchWatch: TerminalMemorySearchWatch | undefined;
|
||||
let subagentPromise: Promise<RecallSubagentResult> | undefined;
|
||||
try {
|
||||
const subagentPromise = runRecallSubagent({
|
||||
subagentPromise = runRecallSubagent({
|
||||
...params,
|
||||
modelRef: resolvedModelRef,
|
||||
abortSignal: controller.signal,
|
||||
@@ -2753,6 +2768,14 @@ async function maybeResolveActiveRecall(params: {
|
||||
} finally {
|
||||
terminalMemorySearchWatch?.stop();
|
||||
clearTimeout(timeoutId);
|
||||
if (!params.config.persistTranscripts) {
|
||||
deleteTransientRecallTranscript(transcriptScope);
|
||||
subagentPromise
|
||||
?.finally(() => {
|
||||
deleteTransientRecallTranscript(transcriptScope);
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user