diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e655f64b..abd96e052 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Web UI: make chat refresh smoothly scroll to the latest messages and suppress new-messages badge flash during manual refresh. - Cron: route text-only isolated agent announces through the shared subagent announce flow; add exponential backoff for repeated errors; preserve future `nextRunAtMs` on restart; include current-boundary schedule matches; prevent stale threadId reuse across targets; and add per-job execution timeout. (#11641) Thanks @tyler6204. - Subagents: stabilize announce timing, preserve compaction metrics across retries, clamp overflow-prone long timeouts, and cap impossible context usage token totals. (#11551) Thanks @tyler6204. - Agents: recover from context overflow caused by oversized tool results (pre-emptive capping + fallback truncation). (#11579) Thanks @tyler6204. diff --git a/ui/src/ui/app-chat.ts b/ui/src/ui/app-chat.ts index b8e09def1..c648a89d1 100644 --- a/ui/src/ui/app-chat.ts +++ b/ui/src/ui/app-chat.ts @@ -202,7 +202,7 @@ export async function handleSendChat( }); } -export async function refreshChat(host: ChatHost) { +export async function refreshChat(host: ChatHost, opts?: { scheduleScroll?: boolean }) { await Promise.all([ loadChatHistory(host as unknown as OpenClawApp), loadSessions(host as unknown as OpenClawApp, { @@ -210,7 +210,9 @@ export async function refreshChat(host: ChatHost) { }), refreshChatAvatar(host), ]); - scheduleChatScroll(host as unknown as Parameters[0]); + if (opts?.scheduleScroll !== false) { + scheduleChatScroll(host as unknown as Parameters[0]); + } } export const flushChatQueueForEvent = flushChatQueue; diff --git a/ui/src/ui/app-lifecycle.ts b/ui/src/ui/app-lifecycle.ts index 32af804fb..9a9826103 100644 --- a/ui/src/ui/app-lifecycle.ts +++ b/ui/src/ui/app-lifecycle.ts @@ -22,6 +22,7 @@ type LifecycleHost = { basePath: string; tab: Tab; chatHasAutoScrolled: boolean; + chatManualRefreshInFlight: boolean; chatLoading: boolean; chatMessages: unknown[]; chatToolMessages: unknown[]; @@ -65,6 +66,9 @@ export function handleDisconnected(host: LifecycleHost) { } export function handleUpdated(host: LifecycleHost, changed: Map) { + if (host.tab === "chat" && host.chatManualRefreshInFlight) { + return; + } if ( host.tab === "chat" && (changed.has("chatMessages") || diff --git a/ui/src/ui/app-render.helpers.ts b/ui/src/ui/app-render.helpers.ts index c12258599..eaf6eabdc 100644 --- a/ui/src/ui/app-render.helpers.ts +++ b/ui/src/ui/app-render.helpers.ts @@ -126,9 +126,23 @@ export function renderChatControls(state: AppViewState) {