refactor: remove stale transcript locator references

This commit is contained in:
Peter Steinberger
2026-05-09 17:58:44 +01:00
parent 3a149f99f7
commit 96d17d1b57
6 changed files with 18 additions and 46 deletions

View File

@@ -210,8 +210,9 @@ Required members:
</ParamField>
`compact` returns a `CompactResult`. When compaction rotates the active
transcript, `result.sessionId` and `result.sessionFile` identify the successor
session that the next retry or turn must use.
transcript, `result.sessionId` identifies the successor session that the next
retry or turn must use. Transcript rows stay in SQLite; compaction does not
handoff a transcript file or locator.
Optional members:

View File

@@ -81,8 +81,8 @@ The returned view is intentionally bounded and safety-filtered:
Both tools accept either a **session key** (like `"main"`) or a **session ID**
from a previous list call.
If you need the exact byte-for-byte transcript, inspect the transcript file on
disk instead of treating `sessions_history` as a raw dump.
If you need the exact byte-for-byte transcript for debugging, export it from
SQLite instead of treating `sessions_history` as a raw dump.
## Sending cross-session messages

View File

@@ -501,7 +501,7 @@ Announce payloads include a stats line at the end (even when wrapped):
- Runtime (e.g. `runtime 5m12s`).
- Token usage (input/output/total).
- Estimated cost when model pricing is configured (`models.providers.*.models[].cost`).
- `sessionKey`, `sessionId`, and transcript path so the main agent can fetch history via `sessions_history` or inspect the file on disk.
- `sessionKey` and `sessionId` so the main agent can fetch history via `sessions_history` or inspect the SQLite transcript rows.
Internal metadata is meant for orchestration only; user-facing replies
should be rewritten in normal assistant voice.

View File

@@ -42,7 +42,7 @@ describe("ensureSessionHeader", () => {
it("creates the transcript header in SQLite without writing a JSONL file", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-session-header-"));
try {
const transcriptLocator = path.join(tempDir, "nested", "session.jsonl");
const legacyTranscriptPath = path.join(tempDir, "nested", "session.jsonl");
const env = {
...process.env,
OPENCLAW_STATE_DIR: path.join(tempDir, "state"),
@@ -54,7 +54,7 @@ describe("ensureSessionHeader", () => {
env,
});
await expect(fs.access(transcriptLocator)).rejects.toThrow();
await expect(fs.access(legacyTranscriptPath)).rejects.toThrow();
const events = loadSqliteSessionTranscriptEvents({
agentId: "main",
sessionId: "session-1",

View File

@@ -53,10 +53,7 @@ async function createCompactionSessionFixture(entry: SessionEntry) {
return { sessionKey, sessionStore };
}
async function rotateCompactionTranscriptLocator(params: {
tempPrefix: string;
newSessionId: string;
}) {
async function rotateCompactionSessionId(params: { tempPrefix: string; newSessionId: string }) {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), params.tempPrefix));
tempDirs.push(tmp);
vi.stubEnv("OPENCLAW_STATE_DIR", tmp);
@@ -547,8 +544,8 @@ describe("incrementCompactionCount", () => {
expect(stored[sessionKey].totalTokensFresh).toBe(true);
});
it("updates sessionId without persisting transcript locators when compaction rotated transcripts", async () => {
const { stored, sessionKey } = await rotateCompactionTranscriptLocator({
it("updates sessionId without persisting transcript locators when compaction rotates sessions", async () => {
const { stored, sessionKey } = await rotateCompactionSessionId({
tempPrefix: "openclaw-compact-rotate-",
newSessionId: "s2",
});
@@ -556,8 +553,8 @@ describe("incrementCompactionCount", () => {
expect(stored[sessionKey]).not.toHaveProperty("transcriptLocator");
});
it("drops legacy fork transcript filenames when compaction rotates transcripts", async () => {
const { stored, sessionKey } = await rotateCompactionTranscriptLocator({
it("drops legacy fork transcript filenames when compaction rotates sessions", async () => {
const { stored, sessionKey } = await rotateCompactionSessionId({
tempPrefix: "openclaw-compact-fork-",
newSessionId: "s2",
});
@@ -565,8 +562,8 @@ describe("incrementCompactionCount", () => {
expect(stored[sessionKey]).not.toHaveProperty("transcriptLocator");
});
it("replaces absolute transcriptLocator paths with sqlite locators during compaction rotation", async () => {
const { stored, sessionKey } = await rotateCompactionTranscriptLocator({
it("drops legacy transcript locator paths during compaction rotation", async () => {
const { stored, sessionKey } = await rotateCompactionSessionId({
tempPrefix: "openclaw-compact-unsafe-",
newSessionId: "s2",
});

View File

@@ -217,41 +217,16 @@ vi.mock("../agents/command/delivery.runtime.js", () => {
});
vi.mock("../config/sessions/transcript-resolve.runtime.js", () => {
const joinPath = (...parts: string[]): string => {
const separator = parts.some((part) => part.includes("\\")) ? "\\" : "/";
const normalizedParts: string[] = [];
for (const [index, part] of parts.entries()) {
const normalized =
index === 0 ? part.replace(/[\\/]+$/u, "") : part.replace(/^[\\/]+|[\\/]+$/gu, "");
if (normalized.length > 0) {
normalizedParts.push(normalized);
}
}
return normalizedParts.join(separator);
};
const resolveTranscriptLocator = (
sessionId: string,
agentId: string,
sessionsDir?: string,
): string =>
joinPath(sessionsDir ?? ".openclaw", "agents", agentId, "sessions", `${sessionId}.jsonl`);
return {
resolveSessionTranscriptTarget: vi.fn(
async (params: {
sessionId: string;
sessionKey: string;
sessionEntry?: { transcriptLocator?: string; sessionId?: string };
sessionStore?: Record<string, { transcriptLocator?: string; sessionId?: string }>;
sessionEntry?: { sessionId?: string };
sessionStore?: Record<string, { sessionId?: string }>;
agentId: string;
threadId?: string | number;
}) => {
const transcriptLocatorFromStorePath =
params.sessionEntry?.transcriptLocator ??
resolveTranscriptLocator(params.sessionId, params.agentId);
const transcriptLocator = params.sessionEntry?.transcriptLocator
? transcriptLocatorFromStorePath
: resolveTranscriptLocator(params.sessionId, params.agentId);
let sessionEntry = params.sessionEntry;
if (params.sessionStore && params.sessionKey) {
const existingEntry =
@@ -261,12 +236,11 @@ vi.mock("../config/sessions/transcript-resolve.runtime.js", () => {
sessionEntry = {
...existingEntry,
sessionId: params.sessionId,
transcriptLocator,
};
params.sessionStore[params.sessionKey] = sessionEntry;
await replaceTestSessionRows(params.agentId, params.sessionStore as never);
}
return { transcriptLocator, sessionEntry };
return { agentId: params.agentId, sessionId: params.sessionId, sessionEntry };
},
),
};