Skip to content

Commit 3c273a1

Browse files
committed
fix: dedupe thread items on resume
1 parent 00cff6f commit 3c273a1

1 file changed

Lines changed: 49 additions & 6 deletions

File tree

src/hooks/useThreads.ts

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,23 +1090,66 @@ function chooseRicherItem(remote: ConversationItem, local: ConversationItem) {
10901090
return remote;
10911091
}
10921092

1093+
function itemSignature(item: ConversationItem) {
1094+
if (item.kind === "message") {
1095+
return `message:${item.role}:${item.text}`;
1096+
}
1097+
if (item.kind === "reasoning") {
1098+
return `reasoning:${item.summary}:${item.content}`;
1099+
}
1100+
if (item.kind === "tool") {
1101+
return `tool:${item.toolType}:${item.title}:${item.detail}`;
1102+
}
1103+
if (item.kind === "diff") {
1104+
return `diff:${item.title}:${item.diff}`;
1105+
}
1106+
if (item.kind === "review") {
1107+
return `review:${item.state}:${item.text}`;
1108+
}
1109+
return null;
1110+
}
1111+
10931112
function mergeThreadItems(
10941113
remoteItems: ConversationItem[],
10951114
localItems: ConversationItem[],
10961115
) {
10971116
if (!localItems.length) {
10981117
return remoteItems;
10991118
}
1100-
const byId = new Map(remoteItems.map((item) => [item.id, item]));
1101-
const merged = remoteItems.map((item) => {
1102-
const local = localItems.find((entry) => entry.id === item.id);
1103-
return local ? chooseRicherItem(item, local) : item;
1119+
const merged = [...remoteItems];
1120+
const byId = new Map(remoteItems.map((item, index) => [item.id, index]));
1121+
const bySignature = new Map<string, number[]>();
1122+
remoteItems.forEach((item, index) => {
1123+
const signature = itemSignature(item);
1124+
if (!signature) {
1125+
return;
1126+
}
1127+
const entries = bySignature.get(signature);
1128+
if (entries) {
1129+
entries.push(index);
1130+
} else {
1131+
bySignature.set(signature, [index]);
1132+
}
11041133
});
1134+
11051135
localItems.forEach((item) => {
1106-
if (!byId.has(item.id)) {
1107-
merged.push(item);
1136+
const byIdIndex = byId.get(item.id);
1137+
if (byIdIndex !== undefined) {
1138+
merged[byIdIndex] = chooseRicherItem(merged[byIdIndex], item);
1139+
return;
11081140
}
1141+
const signature = itemSignature(item);
1142+
if (signature) {
1143+
const matches = bySignature.get(signature);
1144+
if (matches && matches.length > 0) {
1145+
const matchIndex = matches.shift() as number;
1146+
merged[matchIndex] = chooseRicherItem(merged[matchIndex], item);
1147+
return;
1148+
}
1149+
}
1150+
merged.push(item);
11091151
});
1152+
11101153
return merged;
11111154
}
11121155

0 commit comments

Comments
 (0)