Skip to content

fix: simplify approval confirmation flow#2143

Merged
Hmbown merged 2 commits into
Hmbown:mainfrom
reidliu41:fix/approval-one-step
May 25, 2026
Merged

fix: simplify approval confirmation flow#2143
Hmbown merged 2 commits into
Hmbown:mainfrom
reidliu41:fix/approval-one-step

Conversation

@reidliu41
Copy link
Copy Markdown
Contributor

@reidliu41 reidliu41 commented May 25, 2026

Summary

Fixes #1257.

Destructive approval prompts required two matching approval keypresses before a
tool could run. This made common approval flows slower and confusing because the
first keypress only staged the decision.

This PR removes the staged confirmation state. Approval prompts now behave
consistently:

  • Enter commits the currently selected option
  • y / 1 approves once
  • a / 2 approves for the session
  • d / n / 3 denies the current tool
  • Esc aborts the current turn
  • Tab still collapses or expands the approval card
  • v still opens full tool parameters

This also fixes a pre-existing mismatch where Esc emitted an abort decision,
but the downstream handler treated it the same as deny. Esc now cancels the
active turn and marks local in-flight output as interrupted.

The destructive risk badge, impact summary, and warning styling remain visible.
The selected approval row now uses a stronger blue/white highlight for better
contrast.

Reimplements the useful parts of #1459 against current main.

FROM:
image

TO:

image

Testing

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --all-features
  • cargo test --workspace --all-features

Checklist

  • Updated docs or comments as needed
  • Added or updated tests where relevant
  • Verified TUI behavior manually if UI changes

Greptile Summary

This PR simplifies the approval confirmation flow by removing the two-step "stage then confirm" requirement for destructive operations. All risk levels now share the same single-keypress commit behaviour, while the destructive badge, impact summary, and warning styling remain. Esc is also fixed to properly cancel the active turn (via engine_handle.cancel()) rather than being treated identically to a deny.

  • approval.rs: Removes pending_confirm state and commit_or_stage/requires_confirm logic; replaces with a simpler commit_option that immediately emits a decision. All downstream tests are updated to match the one-step behaviour.
  • ui.rs: Extracts ApprovalDecisionEvent + apply_approval_decision for cleanliness; separates Abort from Deny so Esc calls engine_handle.cancel() (consistent with Ctrl+C / shell-cancel paths). The engine's await_tool_approval uses tokio::select! on the cancel token so the pending call is safely unblocked.
  • widgets/mod.rs: Unifies the footer hint across both risk levels, removes staged-confirmation rendering, and switches the selection highlight from SELECTION_BG to DEEPSEEK_BLUE for stronger contrast.

Confidence Score: 5/5

Safe to merge — the simplification is well-scoped and the abort path is consistent with every other turn-cancellation site in the codebase.

The removal of the staged-confirmation state is clean and fully tested. The most load-bearing change — Esc now calling engine_handle.cancel() instead of deny_tool_call() — is sound because the engine's await_tool_approval uses tokio::select! that races the cancel token against the approval channel, so the pending tool call is always unblocked. This pattern already exists in the Ctrl+C and shell-cancel paths. No unresolved tool calls, no dropped state, and the session-denied cache logic is unchanged for the Deny arm.

No files require special attention.

Important Files Changed

Filename Overview
crates/tui/src/tui/approval.rs Removes the two-step staged-confirmation state machine (pending_confirm, commit_or_stage, requires_confirm); replaces with a direct commit_option call. Tests updated to match new one-step behaviour. No logic errors found.
crates/tui/src/tui/ui.rs Extracts approval decision handling into apply_approval_decision. Correctly separates Abort from Deny — cancel() is safe here because the engine's await_tool_approval uses tokio::select! on the cancel token. Consistent with existing Ctrl+C / shell-cancel paths.
crates/tui/src/tui/widgets/mod.rs Simplifies approval rendering: removes staged-confirmation banner, unifies footer hint, introduces approval_option_style helper. Adds a render test for the new DEEPSEEK_BLUE selection highlight. Removes unused option field from ApprovalOptionRow.

Sequence Diagram

sequenceDiagram
    participant User
    participant ApprovalView
    participant UI as UI (apply_approval_decision)
    participant EngineHandle

    Note over User,EngineHandle: Approve / Deny path (all risk levels)
    User->>ApprovalView: y / a / d / Enter / 1 / 2 / 3
    ApprovalView->>ApprovalView: commit_option(option)
    ApprovalView-->>UI: ViewEvent::ApprovalDecision
    alt Approved or ApprovedForSession
        UI->>EngineHandle: approve_tool_call(tool_id)
    else Denied
        UI->>UI: cache approval_key in session_denied
        UI->>EngineHandle: deny_tool_call(tool_id)
    end
    EngineHandle-->>EngineHandle: unblocks await_tool_approval (rx_approval)

    Note over User,EngineHandle: Abort path (Esc cancels the active turn)
    User->>ApprovalView: Esc
    ApprovalView-->>UI: ViewEvent::ApprovalDecision Abort
    UI->>EngineHandle: cancel() sets CancellationToken
    EngineHandle-->>EngineHandle: await_tool_approval select! fires on cancel_token.cancelled()
    UI->>UI: mark_active_turn_cancelled_locally(app)
Loading

Reviews (2): Last reviewed commit: "fix: make approval abort cancel the turn" | Re-trigger Greptile

  Remove staged two-step approval for destructive actions. Enter now commits the
  selected option, while y/a/d still act as direct shortcuts.

  Keep destructive warnings visible and improve selected option contrast in the
  approval modal. Add test coverage for the one-step flow and highlight styling.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request simplifies the TUI approval flow by removing the two-key staged confirmation mechanism for destructive actions. Instead, it implements a direct one-step approval flow where users can commit the highlighted option with Enter or use direct shortcuts (y/a/d), while maintaining prominent warning copy and styling for destructive actions. The associated tests and widgets have been updated to align with this streamlined interaction model, and a new test has been added to verify the contrasting highlight style of selected destructive options. I have no feedback to provide as there are no review comments.

  Treat approval abort separately from deny. Deny rejects only the current tool
  call; abort now cancels the active turn and marks in-flight UI state as
  interrupted.
@reidliu41
Copy link
Copy Markdown
Contributor Author

hi @Hmbown please help to take a look again if you have time. thanks.

@Hmbown Hmbown merged commit c483cd5 into Hmbown:main May 25, 2026
9 checks passed
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.

Please improve the confirmation flow, I don't want to press the Enter key twice every time.

2 participants