summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/components
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/components')
-rw-r--r--packages/cli/src/ui/components/FolderTrustDialog.test.tsx29
-rw-r--r--packages/cli/src/ui/components/FolderTrustDialog.tsx70
2 files changed, 99 insertions, 0 deletions
diff --git a/packages/cli/src/ui/components/FolderTrustDialog.test.tsx b/packages/cli/src/ui/components/FolderTrustDialog.test.tsx
new file mode 100644
index 00000000..01394d0f
--- /dev/null
+++ b/packages/cli/src/ui/components/FolderTrustDialog.test.tsx
@@ -0,0 +1,29 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { render } from 'ink-testing-library';
+import { vi } from 'vitest';
+import { FolderTrustDialog, FolderTrustChoice } from './FolderTrustDialog.js';
+
+describe('FolderTrustDialog', () => {
+ it('should render the dialog with title and description', () => {
+ const { lastFrame } = render(<FolderTrustDialog onSelect={vi.fn()} />);
+
+ expect(lastFrame()).toContain('Do you trust this folder?');
+ expect(lastFrame()).toContain(
+ 'Trusting a folder allows Gemini to execute commands it suggests.',
+ );
+ });
+
+ it('should call onSelect with DO_NOT_TRUST when escape is pressed', () => {
+ const onSelect = vi.fn();
+ const { stdin } = render(<FolderTrustDialog onSelect={onSelect} />);
+
+ stdin.write('\u001B'); // Simulate escape key
+
+ expect(onSelect).toHaveBeenCalledWith(FolderTrustChoice.DO_NOT_TRUST);
+ });
+});
diff --git a/packages/cli/src/ui/components/FolderTrustDialog.tsx b/packages/cli/src/ui/components/FolderTrustDialog.tsx
new file mode 100644
index 00000000..1918998c
--- /dev/null
+++ b/packages/cli/src/ui/components/FolderTrustDialog.tsx
@@ -0,0 +1,70 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { Box, Text, useInput } from 'ink';
+import React from 'react';
+import { Colors } from '../colors.js';
+import {
+ RadioButtonSelect,
+ RadioSelectItem,
+} from './shared/RadioButtonSelect.js';
+
+export enum FolderTrustChoice {
+ TRUST_FOLDER = 'trust_folder',
+ TRUST_PARENT = 'trust_parent',
+ DO_NOT_TRUST = 'do_not_trust',
+}
+
+interface FolderTrustDialogProps {
+ onSelect: (choice: FolderTrustChoice) => void;
+}
+
+export const FolderTrustDialog: React.FC<FolderTrustDialogProps> = ({
+ onSelect,
+}) => {
+ useInput((_, key) => {
+ if (key.escape) {
+ onSelect(FolderTrustChoice.DO_NOT_TRUST);
+ }
+ });
+
+ const options: Array<RadioSelectItem<FolderTrustChoice>> = [
+ {
+ label: 'Trust folder',
+ value: FolderTrustChoice.TRUST_FOLDER,
+ },
+ {
+ label: 'Trust parent folder',
+ value: FolderTrustChoice.TRUST_PARENT,
+ },
+ {
+ label: "Don't trust (esc)",
+ value: FolderTrustChoice.DO_NOT_TRUST,
+ },
+ ];
+
+ return (
+ <Box
+ flexDirection="column"
+ borderStyle="round"
+ borderColor={Colors.AccentYellow}
+ padding={1}
+ width="100%"
+ marginLeft={1}
+ >
+ <Box flexDirection="column" marginBottom={1}>
+ <Text bold>Do you trust this folder?</Text>
+ <Text>
+ Trusting a folder allows Gemini to execute commands it suggests. This
+ is a security feature to prevent accidental execution in untrusted
+ directories.
+ </Text>
+ </Box>
+
+ <RadioButtonSelect items={options} onSelect={onSelect} isFocused />
+ </Box>
+ );
+};