mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:00:42 +00:00
fix(auto-reply): skip replay when retained window is assistant-only
Codex follow-up review on #70898: the `startIdx < kept.length - 1` guard still wrote an assistant-first transcript when every turn inside the retained window was an assistant (e.g. a tail of consecutive assistant messages). That re-creates the exact role-ordering hazard the reset path is recovering from. Advance through the full window and, if no user turn remains, return 0 without touching the target transcript. Missing a few turns of DM continuity is strictly better than re-triggering the conflict. Locked in with a new assertion on the existing unit test. Made-with: Cursor
This commit is contained in:
committed by
Josh Lehman
parent
b3731e2200
commit
339d3759b0
@@ -47,6 +47,15 @@ describe("replayRecentUserAssistantMessages", () => {
|
||||
expect(["user", "assistant"]).toContain(r.message.role);
|
||||
}
|
||||
expect(await call(path.join(root, "missing.jsonl"), path.join(root, "out.jsonl"))).toBe(0);
|
||||
|
||||
const assistantSource = path.join(root, "all-assistant.jsonl");
|
||||
const assistantTarget = path.join(root, "all-assistant-out.jsonl");
|
||||
const onlyAssistants = Array.from({ length: 3 }, () =>
|
||||
j({ message: { role: "assistant", content: "x" } }),
|
||||
).join("");
|
||||
await fs.writeFile(assistantSource, onlyAssistants, "utf8");
|
||||
expect(await call(assistantSource, assistantTarget)).toBe(0);
|
||||
await expect(fs.stat(assistantTarget)).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("skips header for pre-existing targets and aligns the tail to a user turn", async () => {
|
||||
|
||||
@@ -47,9 +47,14 @@ export async function replayRecentUserAssistantMessages(params: {
|
||||
return 0;
|
||||
}
|
||||
let startIdx = Math.max(0, kept.length - max);
|
||||
while (startIdx < kept.length - 1 && kept[startIdx].role === "assistant") {
|
||||
while (startIdx < kept.length && kept[startIdx].role === "assistant") {
|
||||
startIdx += 1;
|
||||
}
|
||||
if (startIdx === kept.length) {
|
||||
// Retained window is assistant-only; replaying would re-create the same
|
||||
// role-ordering hazard this reset path is recovering from.
|
||||
return 0;
|
||||
}
|
||||
const tail = kept.slice(startIdx).map((entry) => entry.line);
|
||||
if (!fs.existsSync(params.targetTranscript)) {
|
||||
await fsp.mkdir(path.dirname(params.targetTranscript), { recursive: true });
|
||||
|
||||
Reference in New Issue
Block a user