{/* One way to say no, not two. The approval gate treats "cancel"
and "decline" identically — `buildElicit` and `enforceApproval`
in `@executor-js/sdk` both raise `ElicitationDeclinedError` for
any non-accept action, and the engine forwards the word only so
the message can read "cancelled" instead of "declined". So this
sends "cancel", the action that also means "I closed this
without answering", which is what a Cancel button says. */}
onComplete({ action: "cancel" })}
>
Cancel
approve(false)}
>
Approve
{/* Offered only when the grant can be scoped to a tool and an
artifact; an unscopable pause gets the plain button rather
than an option that would remember the wrong thing. */}
{pending.grantKey !== null && (
// `modal={false}`: the menu opens on top of a plain fixed
// overlay, not a Radix dialog. A modal menu locks
// `pointer-events` on the body for the duration, and selecting
// an item here unmounts the whole overlay in the same tick —
// the unlock would run against a tree that no longer exists.
approve(true)}
>
Approve and don't ask again
)}