fix: prefer fresh codex activity in conversation timestamps
This commit is contained in:
@@ -355,6 +355,7 @@ function buildConversationItem(state: BossState, project: Project): Conversation
|
||||
const folderLabel = project.threadMeta?.folderName ?? "";
|
||||
const activityIconCount = deriveConversationActivityIconCount(state, project);
|
||||
const topPinnedLabel = isTopPinnedConversation(project) ? "置顶" : undefined;
|
||||
const latestConversationActivityAt = deriveLatestConversationActivityAt(project);
|
||||
const groupMembers = project.isGroup
|
||||
? project.groupMembers.map((member) => ({
|
||||
threadId: member.threadId,
|
||||
@@ -379,8 +380,8 @@ function buildConversationItem(state: BossState, project: Project): Conversation
|
||||
activityIconCount,
|
||||
topPinnedLabel,
|
||||
manualPinned: Boolean(project.pinned && !project.systemPinned),
|
||||
latestReplyAt: project.lastMessageAt,
|
||||
latestReplyLabel: formatTimestampLabel(project.lastMessageAt),
|
||||
latestReplyAt: latestConversationActivityAt,
|
||||
latestReplyLabel: formatTimestampLabel(latestConversationActivityAt),
|
||||
unreadCount: project.unreadCount,
|
||||
riskLevel: project.riskLevel,
|
||||
activeDeviceCount: devices.length,
|
||||
@@ -403,6 +404,31 @@ function buildConversationItem(state: BossState, project: Project): Conversation
|
||||
} satisfies ConversationItem;
|
||||
}
|
||||
|
||||
function deriveLatestConversationActivityAt(project: Project) {
|
||||
const candidates = [
|
||||
project.lastMessageAt,
|
||||
project.threadMeta?.lastObservedCodexActivityAt,
|
||||
project.projectUnderstanding?.updatedAt,
|
||||
project.updatedAt,
|
||||
].filter(Boolean) as string[];
|
||||
|
||||
let latest = candidates[0];
|
||||
let latestTs = latest ? Date.parse(latest) : Number.NEGATIVE_INFINITY;
|
||||
|
||||
for (const candidate of candidates.slice(1)) {
|
||||
const candidateTs = Date.parse(candidate);
|
||||
if (!Number.isFinite(candidateTs)) {
|
||||
continue;
|
||||
}
|
||||
if (!Number.isFinite(latestTs) || candidateTs > latestTs) {
|
||||
latest = candidate;
|
||||
latestTs = candidateTs;
|
||||
}
|
||||
}
|
||||
|
||||
return latest ?? project.lastMessageAt;
|
||||
}
|
||||
|
||||
function deriveConversationActivityIconCount(state: BossState, project: Project): number {
|
||||
let count = 0;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ let runtimeRoot = "";
|
||||
let readState: (typeof import("../src/lib/boss-data"))["readState"];
|
||||
let getConversationHomeItems: (typeof import("../src/lib/boss-projections"))["getConversationHomeItems"];
|
||||
let getConversationFolderView: (typeof import("../src/lib/boss-projections"))["getConversationFolderView"];
|
||||
let formatTimestampLabel: (typeof import("../src/lib/boss-projections"))["formatTimestampLabel"];
|
||||
|
||||
async function setup() {
|
||||
if (runtimeRoot) return;
|
||||
@@ -22,6 +23,7 @@ async function setup() {
|
||||
readState = data.readState;
|
||||
getConversationHomeItems = projections.getConversationHomeItems;
|
||||
getConversationFolderView = projections.getConversationFolderView;
|
||||
formatTimestampLabel = projections.formatTimestampLabel;
|
||||
}
|
||||
|
||||
test.after(async () => {
|
||||
@@ -199,3 +201,35 @@ test("conversation items keep a safe context ring even when no thread snapshot e
|
||||
assert.equal(directThread?.contextBudgetIndicator.percent, 100);
|
||||
assert.equal(directThread?.contextBudgetIndicator.level, "safe");
|
||||
});
|
||||
|
||||
test("conversation items prefer latest observed codex activity over stale last message time", async () => {
|
||||
await setup();
|
||||
const state = await readState();
|
||||
const baseProject = buildImportedThreadProject(
|
||||
"mac-studio",
|
||||
"stale-thread",
|
||||
"Talking",
|
||||
"talking",
|
||||
"树莓派二代查询",
|
||||
"thread-stale",
|
||||
"2026-04-04T06:12:00+08:00",
|
||||
);
|
||||
|
||||
state.projects = state.projects.filter((project) => project.id === "master-agent");
|
||||
state.projects.push(
|
||||
{
|
||||
...baseProject,
|
||||
threadMeta: {
|
||||
...baseProject.threadMeta,
|
||||
lastObservedCodexActivityAt: "2026-04-04T11:48:00+08:00",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const items = getConversationHomeItems(state);
|
||||
const thread = items.find((item) => item.projectId === "stale-thread");
|
||||
|
||||
assert.ok(thread);
|
||||
assert.equal(thread?.latestReplyAt, "2026-04-04T11:48:00+08:00");
|
||||
assert.equal(thread?.latestReplyLabel, formatTimestampLabel("2026-04-04T11:48:00+08:00"));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user