fix(webui): anchor sent prompts during active turns

This commit is contained in:
Xubin Ren
2026-06-22 20:43:27 +08:00
parent fbaa85117b
commit 7170761e47
9 changed files with 333 additions and 56 deletions
+31 -4
View File
@@ -81,6 +81,7 @@ export function ThreadMessages({
() => isStreaming ? currentActivityClusterIndices(units) : new Set<number>(),
[isStreaming, units],
);
const unitKeys = useMemo(() => unitKeysForDisplay(units), [units]);
let nextUserIndex = hiddenUserMessageCount;
return (
@@ -108,7 +109,7 @@ export function ThreadMessages({
if (unit.type === "message" && unit.message.role === "user") nextUserIndex += 1;
return (
<Fragment key={unitKey(unit, index)}>
<Fragment key={unitKeys[index]}>
<div className={marginTop} data-user-prompt-id={userPromptId}>
{unit.type === "activity" ? (
<AgentActivityCluster
@@ -191,14 +192,40 @@ function currentActivityClusterIndices(units: DisplayUnit[]): Set<number> {
return indices;
}
function unitKey(unit: DisplayUnit, index: number): string {
export function unitKeysForDisplay(units: DisplayUnit[]): string[] {
const occurrences = new Map<string, number>();
return units.map((unit, index) => {
const base = unitKeyBase(unit, index);
if (!base.startsWith("turn-") || base.endsWith("-user")) return base;
const next = (occurrences.get(base) ?? 0) + 1;
occurrences.set(base, next);
return `${base}-${next}`;
});
}
function unitKeyBase(unit: DisplayUnit, index: number): string {
if (unit.type === "activity") {
const anchor = unit.messages[0]?.id;
return anchor != null ? `activity-${anchor}` : `activity-idx-${index}`;
const anchor = unit.messages[0];
const turnKey = stableTurnMessageKey(anchor, "activity");
if (turnKey) return turnKey;
const anchorId = anchor?.id;
return anchorId != null ? `activity-${anchorId}` : `activity-idx-${index}`;
}
const turnKey = stableTurnMessageKey(unit.message);
if (turnKey) return turnKey;
return unit.message.id;
}
function stableTurnMessageKey(message: UIMessage | undefined, fallbackPhase?: string): string | null {
if (!message?.turnId) return null;
const phase = message.turnPhase ?? fallbackPhase ?? message.kind ?? message.role;
if (message.role === "user") return `turn-${message.turnId}-user`;
if (message.kind === "trace") {
return `turn-${message.turnId}-${phase}-${message.activitySegmentId ?? "activity"}`;
}
return `turn-${message.turnId}-${phase}`;
}
function marginAfterPrevUnit(prev: DisplayUnit): string {
if (prev.type === "activity") {
return "mt-4";