fix(web): keep rectification sessions listed and persist chats on first send
Independent Staging Quality Gate / validate (push) Failing after 16m52s
Independent Staging Quality Gate / publish (push) Skipped

Empty-consultation filtering is now session_type scoped so birth-time rows stay in the sidebar. Subtitles use updatedAt with sort/group/cursor. New chats stay local until the first send.
This commit is contained in:
jesse-ux
2026-09-21 16:39:32 +08:00
parent f8d65e484d
commit e71e4f9200
21 changed files with 461 additions and 186 deletions
+41
View File
@@ -8,6 +8,9 @@ import {
recencyKeyFor,
sortSessions,
} from "../src/lib/session-groups.ts";
import { sessionSidebarSubtitle } from "../src/lib/session-sidebar-row.ts";
import { shanghaiDateTimeLabel } from "../src/lib/session-shanghai-clock.ts";
import type { ChatSession } from "../src/lib/home-types.ts";
function session(id: string, updatedAt: number, pinned = false) {
return { id, pinned, updatedAt };
@@ -72,6 +75,44 @@ test("mergeSessionPage keeps the local row and skips a duplicate id", () => {
assert.equal(mergeSessionPage([local], incoming)[0]?.updatedAt, 900);
});
test("sidebar subtitle follows updatedAt so the visible clock matches sortSessions", () => {
const createdEarly = Date.parse("2026-09-07T05:42:00.000Z");
const activeLate = Date.parse("2026-09-16T10:01:00.000Z");
const mid = Date.parse("2026-09-17T14:53:00.000Z");
const newest = Date.parse("2026-09-18T00:01:00.000Z");
function row(id: string, createdAt: number, updatedAt: number): ChatSession {
return {
id,
title: id,
theme: "general",
modelId: "m",
messages: [{ role: "user", text: "问一句" }],
createdAt,
updatedAt,
sessionType: "consultation",
rectificationCaseId: null,
chartProfileId: null,
chartProfileName: null,
chartProfileRole: null,
pinned: false,
archivedAt: null,
messagesHydrated: true,
};
}
const earlyCreatedLateActive = row("early-created", createdEarly, activeLate);
const sessions = [
earlyCreatedLateActive,
row("mid", mid, mid),
row("newest", newest, newest),
];
assert.deepEqual(sortSessions(sessions).map((item) => item.id), ["newest", "mid", "early-created"]);
const clocks = sortSessions(sessions).map((item) => sessionSidebarSubtitle(item));
const expected = sortSessions(sessions).map((item) => shanghaiDateTimeLabel(new Date(item.updatedAt)));
assert.deepEqual(clocks, expected);
assert.equal(sessionSidebarSubtitle(earlyCreatedLateActive), shanghaiDateTimeLabel(new Date(activeLate)));
assert.notEqual(sessionSidebarSubtitle(earlyCreatedLateActive), shanghaiDateTimeLabel(new Date(createdEarly)));
});
test("beginSessionPageLoad only starts one in-flight request", () => {
const inFlight = { current: false };
assert.equal(beginSessionPageLoad(inFlight, "cursor"), true);