fix: preserve session source sqlite paths

This commit is contained in:
Peter Steinberger
2026-05-16 04:15:58 +01:00
parent 9e6f86289b
commit 733bf86caa
3 changed files with 71 additions and 3 deletions

View File

@@ -15,6 +15,8 @@ import type { SessionEntry } from "./types.js";
function mergeSessionEntryIntoCombined(params: {
cfg: OpenClawConfig;
combined: Record<string, SessionEntry>;
sourceDatabasePathBySessionKey: Record<string, string>;
sourceDatabasePath: string;
entry: SessionEntry;
agentId: string;
canonicalKey: string;
@@ -50,6 +52,7 @@ function mergeSessionEntryIntoCombined(params: {
spawnedBy,
};
}
params.sourceDatabasePathBySessionKey[canonicalKey] = params.sourceDatabasePath;
}
export function loadCombinedSessionEntriesForGateway(
@@ -58,6 +61,7 @@ export function loadCombinedSessionEntriesForGateway(
): {
databasePath: string;
entries: Record<string, SessionEntry>;
sourceDatabasePathBySessionKey?: Record<string, string>;
} {
const requestedAgentId =
typeof opts.agentId === "string" && opts.agentId.trim()
@@ -71,6 +75,7 @@ export function loadCombinedSessionEntriesForGateway(
)
: resolveAllAgentSessionDatabaseTargetsSync(cfg);
const combined: Record<string, SessionEntry> = {};
const sourceDatabasePathBySessionKey: Record<string, string> = {};
for (const target of targets) {
const agentId = target.agentId;
for (const { sessionKey: key, entry } of listSessionEntries({
@@ -85,6 +90,8 @@ export function loadCombinedSessionEntriesForGateway(
mergeSessionEntryIntoCombined({
cfg,
combined,
sourceDatabasePathBySessionKey,
sourceDatabasePath: target.databasePath,
entry,
agentId,
canonicalKey,
@@ -98,5 +105,5 @@ export function loadCombinedSessionEntriesForGateway(
: targets.length === 1
? targets[0].databasePath
: "(multiple)";
return { databasePath, entries: combined };
return { databasePath, entries: combined, sourceDatabasePathBySessionKey };
}

View File

@@ -861,7 +861,11 @@ export const sessionsHandlers: GatewayRequestHandlers = {
const payload = await measureDiagnosticsTimelineSpan(
"gateway.sessions.list",
async () => {
const { databasePath, entries: store } = measureDiagnosticsTimelineSpanSync(
const {
databasePath,
entries: store,
sourceDatabasePathBySessionKey,
} = measureDiagnosticsTimelineSpanSync(
"gateway.sessions.list.store_load",
() => {
const loaded = loadCombinedSessionEntriesForGateway(cfg, {
@@ -897,6 +901,7 @@ export const sessionsHandlers: GatewayRequestHandlers = {
listSessionsFromStoreAsync({
cfg,
databasePath,
sourceDatabasePathBySessionKey,
store,
modelCatalog,
opts: p,

View File

@@ -6,6 +6,7 @@ import {
} from "../agents/subagent-registry.js";
import type { OpenClawConfig } from "../config/config.js";
import { getSessionEntry, upsertSessionEntry, type SessionEntry } from "../config/sessions.js";
import { replaceSqliteSessionTranscriptEvents } from "../config/sessions/transcript-store.sqlite.js";
import { registerAgentRunContext, resetAgentRunContextForTest } from "../infra/agent-events.js";
import { openOpenClawAgentDatabase } from "../state/openclaw-agent-db.js";
import { withStateDirEnv } from "../test-helpers/state-dir-env.js";
@@ -1171,9 +1172,64 @@ describe("loadCombinedSessionEntriesForGateway includes SQLite-registered agents
},
} as OpenClawConfig;
const { entries } = loadCombinedSessionEntriesForGateway(cfg);
const { entries, sourceDatabasePathBySessionKey } = loadCombinedSessionEntriesForGateway(cfg);
expect(entries["agent:retired:archived-task"]?.sessionId).toBe("s-retired");
expect(sourceDatabasePathBySessionKey?.["agent:retired:archived-task"]).toBe(databasePath);
});
});
test("list rows read transcript fields from registered database paths", async () => {
await withStateDirEnv("openclaw-acp-registered-transcript-path-", async ({ tempRoot }) => {
const databasePath = path.join(tempRoot, "relocated", "work.sqlite");
openOpenClawAgentDatabase({ agentId: "work", path: databasePath });
upsertSessionEntry({
agentId: "work",
path: databasePath,
sessionKey: "agent:work:task",
entry: {
sessionId: "s-work",
updatedAt: 400,
modelProvider: "openai",
model: "gpt-5.4",
},
});
replaceSqliteSessionTranscriptEvents({
agentId: "work",
path: databasePath,
sessionId: "s-work",
events: [
{ type: "session", version: 1, id: "s-work" },
{ message: { role: "user", content: "relocated title" } },
{ message: { role: "assistant", content: "relocated last" } },
],
});
const cfg = {
session: {
mainKey: "main",
},
agents: {
list: [{ id: "main", default: true }, { id: "work" }],
},
} as OpenClawConfig;
const combined = loadCombinedSessionEntriesForGateway(cfg, { agentId: "work" });
expect(Object.keys(combined.entries)).toContain("agent:work:task");
const result = listSessionsFromStore({
cfg,
databasePath: combined.databasePath,
sourceDatabasePathBySessionKey: combined.sourceDatabasePathBySessionKey,
store: combined.entries,
opts: { agentId: "work", includeDerivedTitles: true, includeLastMessage: true },
});
expect(result.sessions[0]).toEqual(
expect.objectContaining({
key: "agent:work:task",
derivedTitle: "relocated title",
lastMessagePreview: "relocated last",
}),
);
});
});