Skip to content

feat: allow dismissing pending user-input questions#1759

Open
mrinc wants to merge 2 commits intopingdotgg:mainfrom
mrinc:t3code/build-notes-check
Open

feat: allow dismissing pending user-input questions#1759
mrinc wants to merge 2 commits intopingdotgg:mainfrom
mrinc:t3code/build-notes-check

Conversation

@mrinc
Copy link
Copy Markdown

@mrinc mrinc commented Apr 5, 2026

Closes #479, Closes #856

Summary

  • Add dismiss/close functionality to the pending user-input question UI so users are no longer forced to answer
  • When dismissed, empty answers {} are sent through the existing command pipeline -- both adapters detect this and inform the model with explicit dismissal text
  • Fixes stuck questions after app restart (Bug: pending plan questions become stuck after app restart #856) since users can now dismiss stale requests, which triggers the existing stale-request cleanup path

Motivation

Currently there is no way to close or dismiss a pending question from the AI agent without answering it. This blocks users who want to skip a question and prompt the agent directly instead. Additionally, when the app restarts while a question is pending, the thread becomes unusable because the question UI persists but submission no longer works (#856).

Approach

Empty answers {} are treated as a dismissal. The frontend sends the existing thread.user-input.respond command with answers: {} -- no new fields, no contract changes, no pipeline changes. Each adapter detects empty answers and fills in "[User dismissed this question without answering]" in its native format so the model receives clear text and can act on it.

Changes (5 files)

Web frontend

  • apps/web/src/components/ChatView.tsx

    • Added onDismissUserInput callback: dispatches thread.user-input.respond with answers: {}, then clears draft state for the request
    • Added useEffect for Escape key: dismisses the active pending user input on keypress
    • Passes onDismiss to ComposerPendingUserInputPanel and onDismissPendingUserInput to ComposerPrimaryActions
  • apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx

    • Added onDismiss prop to panel and inner card components
    • Added X close button (XIcon from lucide-react) with cursor-pointer in the question header row, pushed to the right edge with flex-1 on the label container
    • Button shows tooltip "Dismiss (Esc)" and is disabled while responding
  • apps/web/src/components/chat/ComposerPrimaryActions.tsx

    • Added onDismissPendingUserInput prop
    • Added "Dismiss" ghost button before the Previous/Submit buttons in the pending action row

Server adapters

  • apps/server/src/provider/Layers/ClaudeAdapter.ts

    • In handleAskUserQuestion: after the Deferred resolves, checks if answers are empty (Object.keys(answers).length === 0). If so, builds answers with "[User dismissed this question without answering]" keyed by question text and returns behavior: "allow" with the dismissal answers as updatedInput
  • apps/server/src/codexAppServerManager.ts

    • Added questionIds to PendingUserInputRequest interface
    • Stores question IDs from request.params.questions when item/tool/requestUserInput arrives
    • In respondToUserInput: detects empty answers and builds dismissal answers in native Codex format ({ answers: ["[User dismissed...]"] }) keyed by question ID

No changes needed

  • Contracts -- No schema changes. The existing ProviderUserInputAnswers (Record<string, unknown>) already accepts {}
  • Orchestration pipeline -- decider, ProviderCommandReactor, ProviderService all pass through unchanged
  • apps/web/src/session-logic.ts -- derivePendingUserInputs() already clears pending questions on "user-input.resolved" events and stale-request failures

How users can dismiss

Method Behavior
X button in question panel header Dismisses the active question
"Dismiss" button in composer footer Dismisses the active question
Escape key Dismisses the active question

All three methods send the same thread.user-input.respond command with answers: {}.

Test plan

  • bun typecheck passes (7/7 packages, 0 errors)
  • bun lint passes (0 warnings, 0 errors)
  • bun fmt passes
  • bun run test passes (existing server git test failures are pre-existing environment issues unrelated to this change)
  • Start a session, trigger an AskUserQuestion from the agent, click X button -- question disappears, agent receives deny and can continue
  • Press Escape while question is shown -- same dismiss behavior
  • Click "Dismiss" button in composer footer -- same dismiss behavior
  • Restart the app while a question is pending -- dismiss button allows recovery from the stuck state
  • Answer a question normally (select option, submit) -- existing flow is unaffected
  • Verify the X button and Dismiss button are disabled while a response is in flight

Pictures

Before

image

After

image

Note

Add dismiss support for pending user-input questions via Escape key or dismiss button

  • Adds a dismiss button (X icon) to each pending user-input card in ComposerPendingUserInputPanel and wires a global Escape key handler in ChatView to dismiss the active prompt.
  • Dismissal dispatches a thread.user-input.respond command with an empty answers object, which the server interprets as a dismissal and maps each question ID to a placeholder answer string.
  • The Claude adapter in ClaudeAdapter.ts also handles empty answers by constructing placeholder dismissed answers keyed by question text and returning allow with the updated input.

Macroscope summarized 5d4fcab.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 5, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 65574b5d-3a9c-4541-b082-e997b66b56d3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the size:L 100-499 changed lines (additions + deletions). label Apr 5, 2026
@mrinc mrinc changed the title WIP: feat: allow dismissing pending user-input questions feat: allow dismissing pending user-input questions Apr 5, 2026
@github-actions github-actions bot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Apr 5, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 5, 2026

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature allowing users to dismiss pending input questions via UI button or Escape key. The change modifies runtime behavior across both server orchestration and client UI, sending placeholder text to the AI when questions are dismissed. New features with behavioral changes warrant human review.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge
Copy link
Copy Markdown
Member

how does it look when you're not on the last question?

@mrinc
Copy link
Copy Markdown
Author

mrinc commented Apr 5, 2026

@juliusmarminge

Q1:
image
Q2:
image
Q3:
image

@juliusmarminge
Copy link
Copy Markdown
Member

what about the x button?

i can just imagine that 3rd button will cause overflows when you chagne the viewport?

CleanShot 2026-04-05 at 11 37 43@2x

@mrinc
Copy link
Copy Markdown
Author

mrinc commented Apr 5, 2026

image image image

The X is perfect.
I agree with the dismiss button - takes up a lot of space for no reason - lets remove it and just keep the X

What do you think?

Add dismiss/close functionality to the pending user-input question UI.
Empty answers ({}) are treated as a dismissal -- both adapters detect
this and inform the model with explicit "[User dismissed this question
without answering]" text. No contract or pipeline changes needed.

Closes pingdotgg#479, Closes pingdotgg#856

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mrinc
Copy link
Copy Markdown
Author

mrinc commented Apr 5, 2026

image

Updated - removed the dismiss button

@mrinc mrinc force-pushed the t3code/build-notes-check branch from 029a73f to 0257d73 Compare April 5, 2026 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: pending plan questions become stuck after app restart Dismiss question/plan UI

2 participants