UNPKG

buroventures-harald-code

Version:

Harald Code - AI-powered coding assistant CLI

123 lines 7.15 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { Box, Text, useInput } from 'ink'; import { DiffRenderer } from './DiffRenderer.js'; import { Colors } from '../../colors.js'; import { ToolConfirmationOutcome, } from 'buroventures-harald-code-core'; import { RadioButtonSelect, } from '../shared/RadioButtonSelect.js'; import { MaxSizedBox } from '../shared/MaxSizedBox.js'; export const ToolConfirmationMessage = ({ confirmationDetails, isFocused = true, availableTerminalHeight, terminalWidth, }) => { const { onConfirm } = confirmationDetails; const childWidth = terminalWidth - 2; // 2 for padding useInput((_, key) => { if (!isFocused) return; if (key.escape) { onConfirm(ToolConfirmationOutcome.Cancel); } }); const handleSelect = (item) => onConfirm(item); let bodyContent = null; // Removed contextDisplay here let question; const options = new Array(); // Body content is now the DiffRenderer, passing filename to it // The bordered box is removed from here and handled within DiffRenderer function availableBodyContentHeight() { if (options.length === 0) { // This should not happen in practice as options are always added before this is called. throw new Error('Options not provided for confirmation message'); } if (availableTerminalHeight === undefined) { return undefined; } // Calculate the vertical space (in lines) consumed by UI elements // surrounding the main body content. const PADDING_OUTER_Y = 2; // Main container has `padding={1}` (top & bottom). const MARGIN_BODY_BOTTOM = 1; // margin on the body container. const HEIGHT_QUESTION = 1; // The question text is one line. const MARGIN_QUESTION_BOTTOM = 1; // Margin on the question container. const HEIGHT_OPTIONS = options.length; // Each option in the radio select takes one line. const surroundingElementsHeight = PADDING_OUTER_Y + MARGIN_BODY_BOTTOM + HEIGHT_QUESTION + MARGIN_QUESTION_BOTTOM + HEIGHT_OPTIONS; return Math.max(availableTerminalHeight - surroundingElementsHeight, 1); } if (confirmationDetails.type === 'edit') { if (confirmationDetails.isModifying) { return (_jsxs(Box, { minWidth: "90%", borderStyle: "round", borderColor: Colors.Gray, justifyContent: "space-around", padding: 1, overflow: "hidden", children: [_jsx(Text, { children: "Modify in progress: " }), _jsx(Text, { color: Colors.AccentGreen, children: "Save and close external editor to continue" })] })); } question = `Apply this change?`; options.push({ label: 'Yes, allow once', value: ToolConfirmationOutcome.ProceedOnce, }, { label: 'Yes, allow always', value: ToolConfirmationOutcome.ProceedAlways, }, { label: 'Modify with external editor', value: ToolConfirmationOutcome.ModifyWithEditor, }, { label: 'No, suggest changes (esc)', value: ToolConfirmationOutcome.Cancel, }); bodyContent = (_jsx(DiffRenderer, { diffContent: confirmationDetails.fileDiff, filename: confirmationDetails.fileName, availableTerminalHeight: availableBodyContentHeight(), terminalWidth: childWidth })); } else if (confirmationDetails.type === 'exec') { const executionProps = confirmationDetails; question = `Allow execution of: '${executionProps.rootCommand}'?`; options.push({ label: `Yes, allow once`, value: ToolConfirmationOutcome.ProceedOnce, }, { label: `Yes, allow always ...`, value: ToolConfirmationOutcome.ProceedAlways, }, { label: 'No, suggest changes (esc)', value: ToolConfirmationOutcome.Cancel, }); let bodyContentHeight = availableBodyContentHeight(); if (bodyContentHeight !== undefined) { bodyContentHeight -= 2; // Account for padding; } bodyContent = (_jsx(Box, { flexDirection: "column", children: _jsx(Box, { paddingX: 1, marginLeft: 1, children: _jsx(MaxSizedBox, { maxHeight: bodyContentHeight, maxWidth: Math.max(childWidth - 4, 1), children: _jsx(Box, { children: _jsx(Text, { color: Colors.AccentCyan, children: executionProps.command }) }) }) }) })); } else if (confirmationDetails.type === 'info') { const infoProps = confirmationDetails; const displayUrls = infoProps.urls && !(infoProps.urls.length === 1 && infoProps.urls[0] === infoProps.prompt); question = `Do you want to proceed?`; options.push({ label: 'Yes, allow once', value: ToolConfirmationOutcome.ProceedOnce, }, { label: 'Yes, allow always', value: ToolConfirmationOutcome.ProceedAlways, }, { label: 'No, suggest changes (esc)', value: ToolConfirmationOutcome.Cancel, }); bodyContent = (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginLeft: 1, children: [_jsx(Text, { color: Colors.AccentCyan, children: infoProps.prompt }), displayUrls && infoProps.urls && infoProps.urls.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { children: "URLs to fetch:" }), infoProps.urls.map((url) => (_jsxs(Text, { children: [" - ", url] }, url)))] }))] })); } else { // mcp tool confirmation const mcpProps = confirmationDetails; bodyContent = (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginLeft: 1, children: [_jsxs(Text, { color: Colors.AccentCyan, children: ["MCP Server: ", mcpProps.serverName] }), _jsxs(Text, { color: Colors.AccentCyan, children: ["Tool: ", mcpProps.toolName] })] })); question = `Allow execution of MCP tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"?`; options.push({ label: 'Yes, allow once', value: ToolConfirmationOutcome.ProceedOnce, }, { label: `Yes, always allow tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"`, value: ToolConfirmationOutcome.ProceedAlwaysTool, // Cast until types are updated }, { label: `Yes, always allow all tools from server "${mcpProps.serverName}"`, value: ToolConfirmationOutcome.ProceedAlwaysServer, }, { label: 'No, suggest changes (esc)', value: ToolConfirmationOutcome.Cancel, }); } return (_jsxs(Box, { flexDirection: "column", padding: 1, width: childWidth, children: [_jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", marginBottom: 1, children: bodyContent }), _jsx(Box, { marginBottom: 1, flexShrink: 0, children: _jsx(Text, { wrap: "truncate", children: question }) }), _jsx(Box, { flexShrink: 0, children: _jsx(RadioButtonSelect, { items: options, onSelect: handleSelect, isFocused: isFocused }) })] })); }; //# sourceMappingURL=ToolConfirmationMessage.js.map