Skip to content

Fix/disable refresh during active turn#2487

Open
BingqingLyu wants to merge 3 commits into
mainfrom
fork-pr-66395-fix-disable-refresh-during-active-turn
Open

Fix/disable refresh during active turn#2487
BingqingLyu wants to merge 3 commits into
mainfrom
fork-pr-66395-fix-disable-refresh-during-active-turn

Conversation

@BingqingLyu

@BingqingLyu BingqingLyu commented Apr 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • Problem: The refresh chat data button was only disabled when chatLoading or disconnected, remaining clickable during active agent turns.
  • Why it matters: Clicking refresh mid-turn stalls the live run, resets chat state, and can wedge the gateway session.
  • What changed: Added chatSending, chatRunId, and chatStream guards to the refresh button's disabled condition.
  • What did NOT change (scope boundary): No changes to refresh logic, gateway behavior, or other controls. Only the disabled guard on the refresh button.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause (if applicable)

  • Root cause: The refresh button's disabled binding was missing the busy-state guards (chatSending, chatRunId, chatStream) that are already used by the model select and thinking select controls in the same file.
  • Missing detection / guardrail: No guard for the sending, running, or streaming phases of an agent turn on the refresh button specifically.
  • Contributing context (if known): The model select (line ~490) and thinking select (line ~560) both use a busy variable combining these four flags. The refresh button only had two of them.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: ui/src/ui/app-render.helpers.ts
  • Scenario the test should lock in: Refresh button disabled state includes chatSending, chatRunId, and chatStream
  • Why this is the smallest reliable guardrail: The disabled binding is declarative (Lit ?disabled), so it's evaluated on every render cycle.
  • Existing test that already covers this (if any): N/A
  • If no new test is added, why not: The fix aligns a Lit template binding with the existing busy-state pattern. The guards are reactive properties that Lit re-evaluates on each render. A unit test for a template binding in Lit requires a full render harness and would test the framework, not the logic.

User-visible / Behavior Changes

Refresh button is now grayed out and non-clickable while the agent is sending, running, or streaming a response.

Diagram (if applicable)

Before:
[send message] -> [chatSending=true, chatRunId set, chatStream active] -> refresh button still enabled -> click -> stall/reset

After:
[send message] -> [chatSending=true, chatRunId set, chatStream active] -> refresh button disabled -> no click possible

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Windows 11 x64
  • Runtime/container: Node v22.19.0, npm global install
  • Model/provider: OpenRouter (openrouter/auto)
  • Integration/channel (if any): Control UI WebChat
  • Relevant config (redacted): Default config with OpenRouter provider

Steps

  1. Open Control UI chat tab
  2. Send a message that triggers an agent response
  3. While the agent turn is active (sending/streaming), observe the refresh button

Expected

Refresh button should be disabled (grayed out) during the entire agent turn lifecycle.

Actual (before fix)

Refresh button remained clickable. Clicking it mid-turn reset the chat and stalled the run.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Before (refresh button clickable during active turn)

before

After (refresh button disabled during active turn)

after

Human Verification (required)

  • Verified scenarios: Sent messages via Control UI WebChat, confirmed button is disabled during agent turn, confirmed button re-enables after turn completes.
  • Edge cases checked: Button state on idle chat (enabled), button state during stream (disabled), button state after completion (re-enabled).
  • What you did not verify: Behavior with WebSocket disconnection mid-turn, behavior on mobile Control UI layout.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: Edge case where chatRunId or chatStream are set but the turn is actually stale, leaving the button permanently disabled.
    • Mitigation: The same guards are already used by model select and thinking select without reported issues. The existing lifecycle cleanup (resetChatStateForSessionSwitch) clears all three flags.

Angfr95 added 3 commits April 24, 2026 06:16
…ng gateway

Non-recoverable Slack auth errors (account_inactive, invalid_auth, etc.)
were throwing out of monitorSlackProvider, propagating as unhandled promise
rejections and killing the entire gateway process — taking down all other
channels (Telegram, Discord, etc.) with it.

Replace the three throw sites with return so the Slack provider stops
cleanly while the rest of the gateway keeps running.

Fixes the crash-loop reported in openclaw#62268.
The refresh button was only guarded by chatLoading and connected state,
allowing clicks during active agent turns. This could stall the run,
reset chat state, and wedge the gateway.

Add chatSending, chatRunId, and chatStream guards to match the existing
busy-state pattern used by the model and thinking selects.

Fixes openclaw#65522
@BingqingLyu BingqingLyu added conflicting-group-1 Conflicting PR group 1 — review as a batch conflicting-pr Shares at least one cross-PR dependency with other PRs labels May 26, 2026
@BingqingLyu

Copy link
Copy Markdown
Owner Author

⚠️ Cross-PR Conflict Detected

This PR shares modified code with #2363.

Shared functions:

Function File Also modified by
renderChatControls ui/src/ui/app-render.helpers.ts #2363

Recommendation: Coordinate with #2363 before merging.


Auto-detected by codegraph — a code graph analysis tool built on neug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conflicting-group-1 Conflicting PR group 1 — review as a batch conflicting-pr Shares at least one cross-PR dependency with other PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Control UI: refreshing chat data during an active turn can stall the run and wedge the page/gateway

2 participants