Skip to content

fix(desktop): replay pending approval/ask prompts on (re)connect#3857

Merged
esengine merged 2 commits into
main-v2from
fix/3844-replay-pending-approval
Jun 10, 2026
Merged

fix(desktop): replay pending approval/ask prompts on (re)connect#3857
esengine merged 2 commits into
main-v2from
fix/3844-replay-pending-approval

Conversation

@esengine

Copy link
Copy Markdown
Owner

Problem

A session blocked awaiting a tool approval or ask question can deadlock with no way out: the project tree shows the topic as 待确认 / waiting but no approval modal appears, the Stop button does nothing, and only typing a new message unblocks it (#3844).

Root cause

The "waiting" status and the approval modal come from two independent channels:

  • Status badge — the backend (desktop/tabs.go, topicActivityStatusFromEvent) derives a tab's activity status from the event stream and keeps it server-side, so it survives a WebView reload/reconnect.
  • Approval modal — driven purely by the live ApprovalRequest/AskRequest event in the in-memory frontend reducer (useController.ts), with no restore path: MetaForTab carries no pending prompt, and nothing re-emits it.

So if the live event is ever missed — app restart while blocked, WebView reload, event-stream reconnect, or a subscribe-after-emit race — the controller's requestApproval/Ask goroutine stays blocked, the badge still says waiting, but the modal never rebuilds. (Same class as the dashboard fix in #1770.)

Fix

  • Controller.ReplayPendingPrompts() re-emits the ApprovalRequest/AskRequest event for any prompt still blocking the run loop. promptMu serialises the two, so at most one is outstanding; the loops stay general regardless.
  • asks now retains its questions (new pendingAsk) so an AskRequest replays faithfully.
  • App.ReplayPendingPrompts() fans it across all tabs.
  • The frontend calls it once its event subscription is live (on load/reconnect), so a session left mid-confirmation rebuilds its modal — events route back by tabId exactly like the originals.

Tests

  • internal/control: new replay_pending_test.go — a blocked approval and a blocked ask are both re-emitted identically on ReplayPendingPrompts; an idle controller emits nothing.
  • go test ./internal/control/..., go build ./..., cd desktop && go build ./... && go vet ./... all pass.

Closes #3844

A session blocked awaiting a tool approval or ask question keeps its
"waiting" status server-side (tabs.go derives it from the event stream),
but the frontend approval modal is driven only by the live
ApprovalRequest/AskRequest event with no restore path. A frontend that
reloaded, reconnected, or raced the original event was left showing the
"waiting" badge with no modal and no working stop — a deadlock only a new
message could break (#3844).

Add Controller.ReplayPendingPrompts to re-emit the event for any prompt
still blocking the run loop, expose it on App, and call it from the
frontend once its event subscription is live. asks now retains its
questions so an AskRequest can be replayed faithfully.

Closes #3844
@esengine esengine requested a review from SivanCola as a code owner June 10, 2026 13:16
@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development desktop Wails desktop app (desktop/**) agent Core agent loop (internal/agent, internal/control) labels Jun 10, 2026
The hand-written AppBindings contract and the dev-mock bridge must carry
every bound Go method. ReplayPendingPrompts was missing from both, so the
generated-binding drift check and tsc failed the frontend build.
@esengine esengine merged commit 761e966 into main-v2 Jun 10, 2026
13 checks passed
@esengine esengine deleted the fix/3844-replay-pending-approval branch June 10, 2026 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Core agent loop (internal/agent, internal/control) desktop Wails desktop app (desktop/**) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: 出现待确认字样,但是没有选项。并且无法点击停止按钮。陷入死循环

1 participant