diff --git a/apps/x/apps/renderer/src/App.tsx b/apps/x/apps/renderer/src/App.tsx index e18c9d47..dca1acac 100644 --- a/apps/x/apps/renderer/src/App.tsx +++ b/apps/x/apps/renderer/src/App.tsx @@ -1570,9 +1570,14 @@ function App() { } }, [runId, isStopping, stopClickedAt]) - const handlePermissionResponse = useCallback(async (toolCallId: string, subflow: string[], response: 'approve' | 'deny') => { + const handlePermissionResponse = useCallback(async ( + toolCallId: string, + subflow: string[], + response: 'approve' | 'deny', + scope?: 'once' | 'session' | 'always', + ) => { if (!runId) return - + // Optimistically update the UI immediately setPermissionResponses(prev => { const next = new Map(prev) @@ -1584,11 +1589,11 @@ function App() { next.delete(toolCallId) return next }) - + try { await window.ipc.invoke('runs:authorizePermission', { runId, - authorization: { subflow, toolCallId, response } + authorization: { subflow, toolCallId, response, scope } }) } catch (error) { console.error('Failed to authorize permission:', error) @@ -3057,6 +3062,8 @@ function App() { 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 && isProcessing} response={response} diff --git a/apps/x/apps/renderer/src/components/ai-elements/permission-request.tsx b/apps/x/apps/renderer/src/components/ai-elements/permission-request.tsx index 91b16287..e9cef6dc 100644 --- a/apps/x/apps/renderer/src/components/ai-elements/permission-request.tsx +++ b/apps/x/apps/renderer/src/components/ai-elements/permission-request.tsx @@ -2,8 +2,14 @@ import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, +} from "@/components/ui/dropdown-menu"; import { cn } from "@/lib/utils"; -import { AlertTriangleIcon, CheckCircleIcon, CheckIcon, XCircleIcon, XIcon } from "lucide-react"; +import { AlertTriangleIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, XCircleIcon, XIcon } from "lucide-react"; import type { ComponentProps } from "react"; import { ToolCallPart } from "@x/shared/dist/message.js"; import z from "zod"; @@ -11,6 +17,8 @@ import z from "zod"; export type PermissionRequestProps = ComponentProps<"div"> & { toolCall: z.infer; onApprove?: () => void; + onApproveSession?: () => void; + onApproveAlways?: () => void; onDeny?: () => void; isProcessing?: boolean; response?: 'approve' | 'deny' | null; @@ -20,6 +28,8 @@ export const PermissionRequest = ({ className, toolCall, onApprove, + onApproveSession, + onApproveAlways, onDeny, isProcessing = false, response = null, @@ -117,16 +127,40 @@ export const PermissionRequest = ({ {!isResponded && (
- +
+ + {command && ( + + + + + + + Allow for Session + + + Always Allow + + + + )} +