Skip to content

fix(web): stop auto-dismissing pending questions and approvals on a timeout - #1070

Merged
sailist merged 4 commits into
MoonshotAI:mainfrom
sailist:fix/web-question-timeout
Jun 24, 2026
Merged

fix(web): stop auto-dismissing pending questions and approvals on a timeout#1070
sailist merged 4 commits into
MoonshotAI:mainfrom
sailist:fix/web-question-timeout

Conversation

@sailist

@sailist sailist commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Pending AskUserQuestion requests 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 AskUserQuestion requests after 60s, which dismissed the question in the web UI even though the user had not answered.

What was done:

  • Removed the 60s broker timeout so a question stays pending until the user answers or explicitly dismisses it.
  • Removed the now-unused expires_at field from the question protocol, wire types, and web mappers/reducers/projector.
  • Updated the server, protocol, agent-core, and server-e2e tests that relied on expiry.

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 ApprovalExpiredError instead of waiting for the user's decision.

What was done:

  • Removed the broker timer so pending approvals wait for the user's decision.
  • Kept expires_at populated for the protocol/web contract, but no longer broadcast event.approval.expired or enforce it.
  • Removed the now-obsolete expiry tests.

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 _pending and keeps the session in awaiting_question / awaiting_approval until manual dismiss or shutdown. With the 60s timeouts removed, this leak no longer self-heals.

What was done:

  • For questions, threaded the turn's abort signal through to the question broker and dismissed the pending question when it fires.
  • For approvals (where the abort signal does not reach the broker through the RPC boundary), subscribed to the in-process turn.ended bus event and resolved the session's pending approvals with decision: 'cancelled' when the turn ends for a cancellation reason.
  • Added e2e tests covering both abort paths.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

wbxl2000 and others added 3 commits June 24, 2026 11:47
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-bot

changeset-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8d2f943

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

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

@pkg-pr-new

pkg-pr-new Bot commented Jun 24, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@8d2f943
npx https://pkg.pr.new/@moonshot-ai/kimi-code@8d2f943

commit: 8d2f943

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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.
@sailist
sailist merged commit ff17715 into MoonshotAI:main Jun 24, 2026
9 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants