fix(web): stop auto-dismissing pending questions and approvals on a timeout - #1070
Conversation
The server's question broker auto-expired AskUserQuestion requests after 60s, which dismissed the question even when the user simply needed more time. Remove the timeout, and the now-unused expires_at field, so a question stays pending until the user answers or explicitly dismisses it.
When a prompt is aborted while an AskUserQuestion is pending, the agent's RPC call is cancelled but the broker entry was never settled, so it stayed in _pending and kept the session in awaiting_question until manual dismiss or shutdown. Thread the turn's abort signal to the question broker and dismiss the pending question when it fires.
- remove the broker timer so pending approvals wait for the user instead of being rejected with ApprovalExpiredError - keep expires_at populated for the protocol/web contract, but no longer broadcast event.approval.expired or enforce it
🦋 Changeset detectedLatest commit: 8d2f943 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4542c83e20
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| @@ -121,8 +113,6 @@ export class ApprovalService extends Disposable implements IApprovalService { | |||
| ); | |||
|
|
|||
| return new Promise<ApprovalResponse>((resolve, reject) => { | |||
There was a problem hiding this comment.
Clear approvals when the turn aborts
When a tool permission approval is pending and the user aborts the turn, requestApproval is called with the turn signal (packages/agent-core/src/agent/permission/index.ts:149-158) and the RPC layer now rejects the caller-side wait, but this broker never receives or listens to that signal. Since this change also removed the only timeout cleanup, the approval remains in _pending indefinitely after cancellation, so listPending() keeps the session in awaiting_approval and the stale approval can survive until the user manually resolves it or the server shuts down.
Useful? React with 👍 / 👎.
When a turn is aborted while an approval is pending, the agent's RPC wait is cancelled but the approval broker never settles, so it stays in _pending and keeps the session in awaiting_approval until the user manually resolves it or the server shuts down. With the 60s broker timeout removed, this leak no longer self-heals. Subscribe to the in-process turn.ended bus event and resolve the session's pending approvals with decision 'cancelled' when the turn ends for a cancellation reason. This mirrors the question broker's abort handling without touching agent-core: the turn abort signal never reaches the broker through the RPC boundary, so the broker observes the turn lifecycle over the event bus instead.
Summary
Pending
AskUserQuestionrequests and approvals in the web UI were automatically dismissed after a 60-second broker timeout, even when the user simply needed more time to respond. This PR removes those timeouts so questions and approvals stay pending until the user acts, and fixes a related leak where an aborted turn left a pending question stuck in the broker.1. Stop auto-dismissing questions after a 60 second timeout
Problem: The server's question broker auto-expired
AskUserQuestionrequests after 60s, which dismissed the question in the web UI even though the user had not answered.What was done:
expires_atfield from the question protocol, wire types, and web mappers/reducers/projector.2. Stop auto-expiring approvals after a 60 second timeout
Problem: The server's approval broker had the same 60s timer, rejecting pending approvals with
ApprovalExpiredErrorinstead of waiting for the user's decision.What was done:
expires_atpopulated for the protocol/web contract, but no longer broadcastevent.approval.expiredor enforce it.3. Dismiss pending questions and approvals when their turn is aborted
Problem: When a prompt is aborted while a question or approval is pending, the agent's RPC wait is cancelled but the broker entry is never settled, so it stays in
_pendingand keeps the session inawaiting_question/awaiting_approvaluntil manual dismiss or shutdown. With the 60s timeouts removed, this leak no longer self-heals.What was done:
turn.endedbus event and resolved the session's pending approvals withdecision: 'cancelled'when the turn ends for a cancellation reason.Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.