diff --git a/CHANGELOG.md b/CHANGELOG.md index 97be7c6800b..e4866eed529 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,7 @@ Docs: https://docs.openclaw.ai - Discord/ack reactions: keep automatic ACK reaction auth on the active hydrated Discord account so SecretRef-backed and non-default-account reactions stop falling back to stale default config resolution. (#60081) Thanks @FunJim. - Telegram/model switching: render non-default `/model` callback confirmations with HTML formatting so Telegram shows the selected model in bold instead of raw `**...**` markers. (#60042) Thanks @GitZhangChi. - Plugins/update: allow `openclaw plugins update` to use `--dangerously-force-unsafe-install` for built-in dangerous-code false positives during plugin updates. (#60066) Thanks @huntharo. +- Control UI/chat: keep the Stop button visible during tool-only execution so abortable runs do not fall back to Send while tools are still running. (#54528) thanks @chziyue. ## 2026.4.2 diff --git a/ui/src/ui/views/chat.test.ts b/ui/src/ui/views/chat.test.ts index b6bb9c2f43f..beea4022893 100644 --- a/ui/src/ui/views/chat.test.ts +++ b/ui/src/ui/views/chat.test.ts @@ -689,6 +689,27 @@ describe("chat view", () => { expect(container.textContent).not.toContain("New session"); }); + it("shows a stop button when aborting is available without an active stream", () => { + const container = document.createElement("div"); + render( + renderChat( + createProps({ + canAbort: true, + sending: false, + stream: null, + onAbort: vi.fn(), + }), + ), + container, + ); + + const stopButton = container.querySelector('button[title="Stop"]'); + const sendButton = container.querySelector('button[title="Send"]'); + expect(stopButton).not.toBeNull(); + expect(sendButton).toBeNull(); + expect(container.textContent).not.toContain("New session"); + }); + it("shows a new session button when aborting is unavailable", () => { const container = document.createElement("div"); const onNewSession = vi.fn(); diff --git a/ui/src/ui/views/chat.ts b/ui/src/ui/views/chat.ts index ba93d04bf66..aa8b03eca33 100644 --- a/ui/src/ui/views/chat.ts +++ b/ui/src/ui/views/chat.ts @@ -893,7 +893,7 @@ function renderSlashMenu( export function renderChat(props: ChatProps) { const canCompose = props.connected; - const isBusy = props.sending || props.stream !== null; + const isBusy = props.sending || props.stream !== null || props.canAbort; const canAbort = Boolean(props.canAbort && props.onAbort); const activeSession = props.sessions?.sessions?.find((row) => row.key === props.sessionKey); const reasoningLevel = activeSession?.reasoningLevel ?? "off";