fix(webui): open threads at latest message (#5142)

This commit is contained in:
chengyongru
2026-07-28 18:52:34 +08:00
committed by GitHub
parent 0c6c0438d4
commit 24a392b671
5 changed files with 232 additions and 3 deletions
+9 -1
View File
@@ -186,12 +186,20 @@ export class ThreadCameraController {
}
const deltaSeconds = deltaMs / 1000;
const nextTop = easeOutChase(
const easedTop = easeOutChase(
current,
this.target,
deltaSeconds,
motion,
);
// Some browsers quantize scrollTop writes to whole pixels. Keep the
// ease-out curve, but never let its subpixel tail round back to the same
// position forever.
const minimumStep = Math.min(1, Math.abs(remainingDistance));
const nextTop =
Math.abs(easedTop - current) < minimumStep
? current + Math.sign(remainingDistance) * minimumStep
: easedTop;
const settled = Math.abs(this.target - nextTop) <= motion.settleDistancePx;
this.write(viewport, settled ? this.target : nextTop);
+14 -1
View File
@@ -5,6 +5,7 @@ import type {
type ThreadMotionMode =
| "idle"
| "follow-latest"
| "anchor-prompt"
| "follow-output"
| "follow-completion"
@@ -14,6 +15,7 @@ type ThreadMotionMode =
type AutomaticThreadMotionMode =
| "idle"
| "follow-latest"
| "anchor-prompt"
| "follow-output";
@@ -39,6 +41,11 @@ const THREAD_MOTION_TRANSITIONS: Readonly<
"navigate-latest": "navigating-latest",
"navigate-history": "navigating-history",
"user-scroll": "browsing-history",
"resume-follow": "current-automatic-mode",
},
"follow-latest": {
"navigate-history": "navigating-history",
"user-scroll": "browsing-history",
},
"anchor-prompt": {
"navigate-latest": "navigating-latest",
@@ -350,7 +357,7 @@ export class ThreadMotionCoordinator {
}
private automaticMode(): AutomaticThreadMotionMode {
if (!this.turn.id) return "idle";
if (!this.turn.id) return "follow-latest";
return this.promptPositioned && this.turn.hasOutput
? "follow-output"
: "anchor-prompt";
@@ -408,6 +415,12 @@ export class ThreadMotionCoordinator {
this.followGeometry(geometry);
return;
}
if (this.mode === "follow-latest") {
if (geometry.maxScrollTop - geometry.scrollTop > GEOMETRY_EPSILON_PX) {
this.camera.jumpTo(geometry.maxScrollTop);
}
return;
}
if (this.isHistoryMode() || !this.turn.id) return;
if (!this.turn.promptId && this.turn.entry !== "restored") {
this.mode = "anchor-prompt";