/** * @license * Copyright 2026 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { Box, Text } from 'ink'; import type React from 'react'; import { useCallback, useRef } from 'react'; import { PolicyIntegrityManager, type Config, type PolicyUpdateConfirmationRequest, } from '@google/gemini-cli-core'; import { theme } from '../semantic-colors.js'; import { RadioButtonSelect, type RadioSelectItem, } from './shared/RadioButtonSelect.js'; import { useKeypress } from '../hooks/useKeypress.js'; import { Command } from '../key/keyMatchers.js'; import { useKeyMatchers } from '../hooks/useKeyMatchers.js'; export enum PolicyUpdateChoice { ACCEPT = 'accept', IGNORE = 'ignore', } interface PolicyUpdateDialogProps { config: Config; request: PolicyUpdateConfirmationRequest; onClose: () => void; } export const PolicyUpdateDialog: React.FC = ({ config, request, onClose, }) => { const keyMatchers = useKeyMatchers(); const isProcessing = useRef(false); const handleSelect = useCallback( async (choice: PolicyUpdateChoice) => { if (isProcessing.current) { return; } isProcessing.current = true; try { if (choice === PolicyUpdateChoice.ACCEPT) { const integrityManager = new PolicyIntegrityManager(); await integrityManager.acceptIntegrity( request.scope, request.identifier, request.newHash, ); await config.loadWorkspacePolicies(request.policyDir); } onClose(); } finally { isProcessing.current = false; } }, [config, request, onClose], ); useKeypress( (key) => { if (keyMatchers[Command.ESCAPE](key)) { onClose(); return true; } return false; }, { isActive: true }, ); const options: Array> = [ { label: 'Accept and Load', value: PolicyUpdateChoice.ACCEPT, key: 'accept', }, { label: 'Ignore (Use Default Policies)', value: PolicyUpdateChoice.IGNORE, key: 'ignore', }, ]; return ( New or changed {request.scope} policies detected Location: {request.identifier} Do you want to accept and load these policies? ); };