Compare commits

...
Author SHA1 Message Date
paseo-bot[bot]andIvan Malison da09a5711a test(app): reproduce duplicated replies after cursorless cache restore
Preserve the reply/prompt/reply reproduction through the timeline owner
and SQLite cache. The missing cache range is deliberately supplied to
isolate the condition reported in #4255; its production during archive
and reopen remains unverified. This test intentionally fails on main.

Co-authored-by: Ivan Malison <IvanMalison@gmail.com>
2026-10-17 11:39:17 +02:00
+78
View File
@@ -595,6 +595,84 @@ function createSqliteCache() {
}
describe("SQLite baseline restoration", () => {
it("does not duplicate a conversation restored from display-only SQLite history", async () => {
useSessionStore.getState().initializeSession(SERVER_ID, null);
const { cache, database } = createSqliteCache();
cache.setHosts([SERVER_ID]);
const timestamp = new Date("2026-08-26T10:00:00.000Z");
cache.commitTimeline(SERVER_ID, AGENT_ID, {
agentId: AGENT_ID,
items: [
{ kind: "user_message", id: "prompt", messageId: "prompt", text: "Say BASS_OK", timestamp },
{ kind: "assistant_message", id: "reply", text: "BASS_OK", timestamp },
],
range: null,
hasOlder: false,
});
await cache.flush();
const owner = createOwner(cache);
try {
owner.replaceVisibleAgentIds("test", [AGENT_ID]);
await expect
.poll(
() =>
selectAgentTimelineState(useSessionStore.getState().sessions[SERVER_ID], AGENT_ID)
.status,
)
.toBe("painted");
owner.applyTimelineResponse({
requestId: "reopened-tail",
agentId: AGENT_ID,
agent: null,
direction: "tail",
projection: "projected",
reset: false,
epoch: "new-epoch",
window: { minSeq: 1, maxSeq: 2, nextSeq: 3 },
startCursor: { epoch: "new-epoch", seq: 1 },
endCursor: { epoch: "new-epoch", seq: 2 },
entries: [
{
provider: "test",
item: { type: "user_message", messageId: "prompt", text: "Say BASS_OK" },
timestamp: timestamp.toISOString(),
seqStart: 1,
seqEnd: 1,
sourceSeqRanges: [{ startSeq: 1, endSeq: 1 }],
collapsed: [],
},
{
provider: "test",
item: { type: "assistant_message", messageId: "reply", text: "BASS_OK" },
timestamp: timestamp.toISOString(),
seqStart: 2,
seqEnd: 2,
sourceSeqRanges: [{ startSeq: 2, endSeq: 2 }],
collapsed: [],
},
],
error: null,
hasNewer: false,
hasOlder: false,
staleCursor: false,
gap: false,
});
const timeline = selectAgentTimelineState(
useSessionStore.getState().sessions[SERVER_ID],
AGENT_ID,
);
expect(timeline).toMatchObject({
status: "synced",
items: [
{ kind: "user_message", text: "Say BASS_OK" },
{ kind: "assistant_message", text: "BASS_OK" },
],
});
} finally {
owner.dispose();
database.close();
}
});
it.each([false, true])(
"keeps display-only cached history under a live event (synced=%s)",
async (synced) => {