Merge pull request #730 from rowboatlabs/fix/remove-dead-grant-buttons

fix(x): hide grant-scope buttons where no grant persistence exists
This commit is contained in:
Ramnique Singh 2026-07-11 00:05:04 +05:30 committed by GitHub
commit 235f5802b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 10 additions and 9 deletions

View file

@ -3150,7 +3150,6 @@ function App() {
toolCallId: string,
subflow: string[],
response: 'approve' | 'deny',
scope?: 'once' | 'session' | 'always',
) => {
if (!runId) return
@ -3159,7 +3158,6 @@ function App() {
await sessionChat.respondToPermission(
toolCallId,
response === 'approve' ? 'allow' : 'deny',
scope ? { scope } : undefined,
)
} catch (error) {
console.error('Failed to authorize permission:', error)
@ -6834,8 +6832,6 @@ function App() {
toolCall={permRequest.toolCall}
permission={permRequest.permission}
onApprove={() => handlePermissionResponse(permRequest.toolCall.toolCallId, permRequest.subflow, 'approve')}
onApproveSession={() => handlePermissionResponse(permRequest.toolCall.toolCallId, permRequest.subflow, 'approve', 'session')}
onApproveAlways={() => handlePermissionResponse(permRequest.toolCall.toolCallId, permRequest.subflow, 'approve', 'always')}
onDeny={() => handlePermissionResponse(permRequest.toolCall.toolCallId, permRequest.subflow, 'deny')}
isProcessing={isActive && activeIsWorking}
response={response}

View file

@ -67,6 +67,13 @@ export const PermissionRequest = ({
const isResponded = response !== null;
const isApproved = response === 'approve';
// Scope actions ("Allow for Session"/"Always Allow") render only when the
// caller wires them: the legacy code-mode path persists grants, but the
// turns path has no grant persistence yet and must not show dead buttons.
const hasScopeActions =
Boolean(onApproveSession || onApproveAlways) &&
Boolean(command || filePermission);
// Once a response is chosen, collapse the details to just the header.
// Users can click the header to expand them again.
const [expanded, setExpanded] = useState(false);
@ -180,12 +187,12 @@ export const PermissionRequest = ({
size="sm"
onClick={onApprove}
disabled={isProcessing}
className={cn("flex-1", (command || filePermission) && "rounded-r-none")}
className={cn("flex-1", hasScopeActions && "rounded-r-none")}
>
<CheckIcon className="size-4" />
Approve
</Button>
{(command || filePermission) && (
{hasScopeActions && (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button

View file

@ -170,7 +170,7 @@ interface ChatSidebarProps {
allPermissionRequests?: ChatTabViewState['allPermissionRequests']
permissionResponses?: ChatTabViewState['permissionResponses']
autoPermissionDecisions?: ChatTabViewState['autoPermissionDecisions']
onPermissionResponse?: (toolCallId: string, subflow: string[], response: PermissionResponse, scope?: 'once' | 'session' | 'always') => void
onPermissionResponse?: (toolCallId: string, subflow: string[], response: PermissionResponse) => void
onAskHumanResponse?: (toolCallId: string, subflow: string[], response: string) => void
isToolOpenForTab?: (tabId: string, toolId: string) => boolean
onToolOpenChangeForTab?: (tabId: string, toolId: string, open: boolean) => void
@ -706,8 +706,6 @@ export function ChatSidebar({
toolCall={permRequest.toolCall}
permission={permRequest.permission}
onApprove={() => onPermissionResponse(permRequest.toolCall.toolCallId, permRequest.subflow, 'approve')}
onApproveSession={() => onPermissionResponse(permRequest.toolCall.toolCallId, permRequest.subflow, 'approve', 'session')}
onApproveAlways={() => onPermissionResponse(permRequest.toolCall.toolCallId, permRequest.subflow, 'approve', 'always')}
onDeny={() => onPermissionResponse(permRequest.toolCall.toolCallId, permRequest.subflow, 'deny')}
isProcessing={isActive && isProcessing && !isWaitingOnHuman}
response={response}