fix(sessions): repair migrated paths across short reads (#109400)

This commit is contained in:
Wynne668
2026-08-01 12:04:51 +08:00
committed by GitHub
parent 441d6ab254
commit 3be2964fc7
2 changed files with 34 additions and 15 deletions
+32 -14
View File
@@ -847,21 +847,39 @@ describe("doctor legacy state migrations", () => {
},
});
const detected = await detectLegacyStateMigrations({
cfg: {},
env: { OPENCLAW_STATE_DIR: root } as NodeJS.ProcessEnv,
});
expect(detected.preview).toContain(
`- Sessions: repair migrated transcript paths in ${path.join(targetDir, "sessions.json")}`,
);
const realReadSync = fs.readSync.bind(fs);
let shortReadCalls = 0;
const readSpy = vi.spyOn(fs, "readSync").mockImplementation(((
fd: number,
buffer: NodeJS.ArrayBufferView,
offset: number,
length: number,
position: fs.ReadPosition | null,
) => {
shortReadCalls += 1;
return realReadSync(fd, buffer, offset, Math.min(length, 16), position);
}) as typeof fs.readSync);
const result = await runLegacyStateMigrations({ detected });
expect(result.warnings).toStrictEqual([]);
expect(result.changes).toContain("Repaired migrated session transcript paths");
const store = JSON.parse(
fs.readFileSync(path.join(targetDir, "sessions.json"), "utf8"),
) as Record<string, object>;
expect(store["agent:main:main"]).not.toHaveProperty("sessionFile");
try {
const detected = await detectLegacyStateMigrations({
cfg: {},
env: { OPENCLAW_STATE_DIR: root } as NodeJS.ProcessEnv,
});
expect(detected.preview).toContain(
`- Sessions: repair migrated transcript paths in ${path.join(targetDir, "sessions.json")}`,
);
const result = await runLegacyStateMigrations({ detected });
expect(result.warnings).toStrictEqual([]);
expect(result.changes).toContain("Repaired migrated session transcript paths");
const store = JSON.parse(
fs.readFileSync(path.join(targetDir, "sessions.json"), "utf8"),
) as Record<string, object>;
expect(store["agent:main:main"]).not.toHaveProperty("sessionFile");
expect(shortReadCalls).toBeGreaterThan(1);
} finally {
readSpy.mockRestore();
}
});
it("does not bind stale session metadata to a colliding target transcript", async () => {
+2 -1
View File
@@ -29,6 +29,7 @@ import {
parseAgentSessionKey,
} from "../routing/session-key.js";
import { normalizeSessionKeyPreservingOpaquePeerIds } from "../sessions/session-key-utils.js";
import { readFileWindowFullySync } from "./file-read.js";
import { sameFileIdentity } from "./fs-safe-advanced.js";
import { expandHomePrefix } from "./home-dir.js";
import { isWithinDir } from "./path-safety.js";
@@ -434,7 +435,7 @@ export function resolveStaleLegacySessionFile(params: {
const fd = fs.openSync(targetSessionFile, "r");
try {
const buffer = Buffer.alloc(8192);
const bytesRead = fs.readSync(fd, buffer, 0, buffer.length, 0);
const bytesRead = readFileWindowFullySync(fd, buffer, 0);
if (bytesRead <= 0) {
return undefined;
}