diff --git a/src/commands/doctor-heartbeat-main-session-repair.ts b/src/commands/doctor-heartbeat-main-session-repair.ts index 0734f4d2376..d90331b0d3f 100644 --- a/src/commands/doctor-heartbeat-main-session-repair.ts +++ b/src/commands/doctor-heartbeat-main-session-repair.ts @@ -1,7 +1,10 @@ import { isHeartbeatOkResponse, isHeartbeatUserMessage } from "../auto-reply/heartbeat-filter.js"; import { formatFilesystemTimestamp } from "../config/sessions/artifacts.js"; import { resolveMainSessionKey } from "../config/sessions/main-session.js"; -import { resolveSessionFilePath, type SessionFilePathOptions } from "../config/sessions/paths.js"; +import { + resolveSessionTranscriptLocator, + type SessionTranscriptLocatorOptions, +} from "../config/sessions/paths.js"; import { deleteSessionEntry, getSessionEntry, @@ -180,7 +183,7 @@ export async function repairHeartbeatPoisonedMainSession(params: { cfg: OpenClawConfig; store: Record; stateDir: string; - sessionPathOpts: SessionFilePathOptions; + sessionPathOpts: SessionTranscriptLocatorOptions; prompter: DoctorPrompterLike; warnings: string[]; changes: string[]; @@ -192,7 +195,11 @@ export async function repairHeartbeatPoisonedMainSession(params: { } let transcriptPath: string | undefined; try { - transcriptPath = resolveSessionFilePath(mainEntry.sessionId, mainEntry, params.sessionPathOpts); + transcriptPath = resolveSessionTranscriptLocator( + mainEntry.sessionId, + mainEntry, + params.sessionPathOpts, + ); } catch { transcriptPath = undefined; } diff --git a/src/commands/doctor-state-integrity.ts b/src/commands/doctor-state-integrity.ts index 0e7afdc985c..cde444220a0 100644 --- a/src/commands/doctor-state-integrity.ts +++ b/src/commands/doctor-state-integrity.ts @@ -12,7 +12,7 @@ import { resolveOAuthDir, resolveStateDir } from "../config/paths.js"; import { isPrimarySessionTranscriptFileName } from "../config/sessions/artifacts.js"; import { resolveMainSessionKey } from "../config/sessions/main-session.js"; import { - resolveSessionFilePath, + resolveSessionTranscriptLocator, resolveSessionTranscriptsDirForAgent, } from "../config/sessions/paths.js"; import { listSessionEntries, upsertSessionEntry } from "../config/sessions/store.js"; @@ -884,7 +884,7 @@ export async function noteStateIntegrity( if (!sessionId) { return false; } - const transcriptPath = resolveSessionFilePath(sessionId, entry, sessionPathOpts); + const transcriptPath = resolveSessionTranscriptLocator(sessionId, entry, sessionPathOpts); return !hasSessionTranscript({ agentId, sessionId, transcriptPath }); }); if (missing.length > 0) { @@ -972,7 +972,7 @@ export async function noteStateIntegrity( const mainKey = resolveMainSessionKey(cfg); const mainEntry = store[mainKey]; if (mainEntry?.sessionId) { - const transcriptPath = resolveSessionFilePath( + const transcriptPath = resolveSessionTranscriptLocator( mainEntry.sessionId, mainEntry, sessionPathOpts, @@ -1005,7 +1005,7 @@ export async function noteStateIntegrity( try { referencedTranscriptPaths.add( resolveComparableTranscriptPath( - resolveSessionFilePath(entry.sessionId, entry, sessionPathOpts), + resolveSessionTranscriptLocator(entry.sessionId, entry, sessionPathOpts), ), ); } catch { diff --git a/src/config/sessions.test.ts b/src/config/sessions.test.ts index 1b0ae56e3da..fec69bb3b96 100644 --- a/src/config/sessions.test.ts +++ b/src/config/sessions.test.ts @@ -13,7 +13,7 @@ import { resolveSessionKey, updateLastRoute, } from "./sessions.js"; -import { resolveSessionFilePath } from "./sessions/paths.js"; +import { resolveSessionTranscriptLocator } from "./sessions/paths.js"; import { deleteSessionEntry, listSessionEntries, @@ -602,7 +602,7 @@ describe("sessions", () => { it("uses agent id when resolving session file fallback paths", () => { withStateDir("/custom/state", () => { - const sessionFile = resolveSessionFilePath("sess-2", undefined, { + const sessionFile = resolveSessionTranscriptLocator("sess-2", undefined, { agentId: "codex", }); expect(sessionFile).toBe( @@ -615,7 +615,7 @@ describe("sessions", () => { withStateDir(path.resolve("/different/state"), () => { const originalBase = path.resolve("/original/state"); const bot2Session = path.join(originalBase, "agents", "bot2", "sessions", "sess-1.jsonl"); - const sessionFile = resolveSessionFilePath( + const sessionFile = resolveSessionTranscriptLocator( "sess-1", { sessionFile: bot2Session }, { agentId: "bot1" }, @@ -646,7 +646,7 @@ describe("sessions", () => { agentId: "bot1", sessionId: "sess-1", }); - const sessionFile = resolveSessionFilePath( + const sessionFile = resolveSessionTranscriptLocator( "sess-1", { sessionFile: locator }, { agentId: "bot1" }, @@ -661,7 +661,7 @@ describe("sessions", () => { agentId: "bot2", sessionId: "sess-1", }); - const sessionFile = resolveSessionFilePath( + const sessionFile = resolveSessionTranscriptLocator( "sess-1", { sessionFile: bot2Locator }, { agentId: "bot1" }, diff --git a/src/config/sessions/paths.ts b/src/config/sessions/paths.ts index 0d8302785f1..2b25fb09e14 100644 --- a/src/config/sessions/paths.ts +++ b/src/config/sessions/paths.ts @@ -23,7 +23,7 @@ export function resolveSessionTranscriptsDirForAgent( return resolveAgentSessionsDir(agentId, env, homedir); } -export type SessionFilePathOptions = { +export type SessionTranscriptLocatorOptions = { agentId?: string; }; @@ -95,10 +95,10 @@ export function isSqliteSessionTranscriptLocator(locator: string | undefined): b return typeof locator === "string" && parseSqliteSessionTranscriptLocator(locator) !== undefined; } -export function resolveSessionFilePath( +export function resolveSessionTranscriptLocator( sessionId: string, entry?: { sessionFile?: string }, - opts?: SessionFilePathOptions, + opts?: SessionTranscriptLocatorOptions, ): string { const candidate = entry?.sessionFile?.trim(); const parsed = candidate ? parseSqliteSessionTranscriptLocator(candidate) : undefined; diff --git a/src/config/sessions/sessions.test.ts b/src/config/sessions/sessions.test.ts index 4ae551660e7..9c714f3bfab 100644 --- a/src/config/sessions/sessions.test.ts +++ b/src/config/sessions/sessions.test.ts @@ -8,7 +8,7 @@ import type { SessionConfig } from "../types.base.js"; import { resolveSessionLifecycleTimestamps } from "./lifecycle.js"; import { createSqliteSessionTranscriptLocator, - resolveSessionFilePath, + resolveSessionTranscriptLocator, validateSessionId, } from "./paths.js"; import { evaluateSessionFreshness, resolveSessionResetPolicy } from "./reset.js"; @@ -38,7 +38,7 @@ describe("session path safety", () => { }); it("ignores legacy sessionFile paths", () => { - const resolved = resolveSessionFilePath("sess-1", { + const resolved = resolveSessionTranscriptLocator("sess-1", { sessionFile: "/tmp/openclaw/agents/work/not-sessions/abc-123.jsonl", }); expect(resolved).toBe(createSqliteSessionTranscriptLocator({ sessionId: "sess-1" })); @@ -46,7 +46,7 @@ describe("session path safety", () => { it("uses SQLite transcript locators instead of runtime JSONL paths by default", () => { expect( - resolveSessionFilePath("sess-1", { + resolveSessionTranscriptLocator("sess-1", { sessionFile: "/tmp/openclaw/agents/main/sessions/legacy.jsonl", }), ).toBe(createSqliteSessionTranscriptLocator({ sessionId: "sess-1" }));