fix: prefer freshest duplicate row promotion

This commit is contained in:
Tak Hoffman
2026-03-26 07:54:43 -05:00
parent cc077ef1ef
commit fde3871ee7
2 changed files with 36 additions and 3 deletions

View File

@@ -19,6 +19,7 @@ import {
listSessionsFromStore,
loadCombinedSessionStoreForGateway,
loadSessionEntry,
migrateAndPruneGatewaySessionStoreKey,
parseGroupKey,
pruneLegacyStoreKeys,
resolveGatewaySessionStoreTarget,
@@ -389,6 +390,35 @@ describe("gateway session utils", () => {
expect(Object.keys(store).toSorted()).toEqual(["agent:ops:work"]);
});
test("migrateAndPruneGatewaySessionStoreKey promotes the freshest duplicate row", () => {
const cfg = {
session: { mainKey: "main" },
agents: { list: [{ id: "main", default: true }] },
} as OpenClawConfig;
const store: Record<string, SessionEntry> = {
"agent:main:Main": {
sessionId: "sess-stale",
updatedAt: 1,
} as SessionEntry,
"agent:main:MAIN": {
sessionId: "sess-fresh",
updatedAt: 2,
} as SessionEntry,
};
const result = migrateAndPruneGatewaySessionStoreKey({
cfg,
key: "agent:main:main",
store,
});
expect(result.primaryKey).toBe("agent:main:main");
expect(result.entry?.sessionId).toBe("sess-fresh");
expect(store["agent:main:main"]?.sessionId).toBe("sess-fresh");
expect(store["agent:main:MAIN"]).toBeUndefined();
expect(store["agent:main:Main"]).toBeUndefined();
});
test("listAgentsForGateway rejects avatar symlink escapes outside workspace", () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "session-utils-avatar-outside-"));
const workspace = path.join(root, "workspace");

View File

@@ -483,9 +483,12 @@ export function migrateAndPruneGatewaySessionStoreKey(params: {
});
const primaryKey = target.canonicalKey;
if (!params.store[primaryKey]) {
const existingKey = target.storeKeys.find((candidate) => Boolean(params.store[candidate]));
if (existingKey) {
params.store[primaryKey] = params.store[existingKey];
const freshestMatch = resolveFreshestSessionStoreMatchFromStoreKeys(
params.store,
target.storeKeys,
);
if (freshestMatch) {
params.store[primaryKey] = freshestMatch.entry;
}
}
pruneLegacyStoreKeys({