import React, { useCallback, useMemo } from 'react' import { getOriginalCwd } from '../../bootstrap/state.js' import { Box, Text, useTheme } from '../../ink.js' import { sanitizeToolNameForAnalytics } from '../../services/analytics/metadata.js' import { env } from '../../utils/env.js' import { shouldShowAlwaysAllowOptions } from '../../utils/permissions/permissionsLoader.js' import { truncateToLines } from '../../utils/stringUtils.js' import { logUnaryEvent } from '../../utils/unaryLogging.js' import { type UnaryEvent, usePermissionRequestLogging } from './hooks.js' import { PermissionDialog } from './PermissionDialog.js' import { PermissionPrompt, type PermissionPromptOption, type ToolAnalyticsContext, } from './PermissionPrompt.js' import type { PermissionRequestProps } from './PermissionRequest.js' import { PermissionRuleExplanation } from './PermissionRuleExplanation.js' type FallbackOptionValue = 'yes' | 'yes-dont-ask-again' | 'no' export function FallbackPermissionRequest({ toolUseConfirm, onDone, onReject, verbose: _verbose, workerBadge, }: PermissionRequestProps): React.ReactNode { const [theme] = useTheme() // TODO: Avoid these special cases const originalUserFacingName = toolUseConfirm.tool.userFacingName( toolUseConfirm.input as never, ) const userFacingName = originalUserFacingName.endsWith(' (MCP)') ? originalUserFacingName.slice(0, -6) : originalUserFacingName const unaryEvent = useMemo( () => ({ completion_type: 'tool_use_single', language_name: 'none', }), [], ) usePermissionRequestLogging(toolUseConfirm, unaryEvent) const handleSelect = useCallback( (value: FallbackOptionValue, feedback?: string) => { switch (value) { case 'yes': void logUnaryEvent({ completion_type: 'tool_use_single', event: 'accept', metadata: { language_name: 'none', message_id: toolUseConfirm.assistantMessage.message.id, platform: env.platform, }, }) toolUseConfirm.onAllow(toolUseConfirm.input, [], feedback) onDone() break case 'yes-dont-ask-again': { void logUnaryEvent({ completion_type: 'tool_use_single', event: 'accept', metadata: { language_name: 'none', message_id: toolUseConfirm.assistantMessage.message.id, platform: env.platform, }, }) toolUseConfirm.onAllow(toolUseConfirm.input, [ { type: 'addRules', rules: [ { toolName: toolUseConfirm.tool.name, }, ], behavior: 'allow', destination: 'localSettings', }, ]) onDone() break } case 'no': void logUnaryEvent({ completion_type: 'tool_use_single', event: 'reject', metadata: { language_name: 'none', message_id: toolUseConfirm.assistantMessage.message.id, platform: env.platform, }, }) toolUseConfirm.onReject(feedback) onReject() onDone() break } }, [toolUseConfirm, onDone, onReject], ) const handleCancel = useCallback(() => { void logUnaryEvent({ completion_type: 'tool_use_single', event: 'reject', metadata: { language_name: 'none', message_id: toolUseConfirm.assistantMessage.message.id, platform: env.platform, }, }) toolUseConfirm.onReject() onReject() onDone() }, [toolUseConfirm, onDone, onReject]) const originalCwd = getOriginalCwd() const showAlwaysAllowOptions = shouldShowAlwaysAllowOptions() const options = useMemo((): PermissionPromptOption[] => { const result: PermissionPromptOption[] = [ { label: 'Yes', value: 'yes', feedbackConfig: { type: 'accept' }, }, ] if (showAlwaysAllowOptions) { result.push({ label: ( Yes, and don't ask again for {userFacingName}{' '} commands in {originalCwd} ), value: 'yes-dont-ask-again', }) } result.push({ label: 'No', value: 'no', feedbackConfig: { type: 'reject' }, }) return result }, [userFacingName, originalCwd, showAlwaysAllowOptions]) const toolAnalyticsContext = useMemo( (): ToolAnalyticsContext => ({ toolName: sanitizeToolNameForAnalytics(toolUseConfirm.tool.name), isMcp: toolUseConfirm.tool.isMcp ?? false, }), [toolUseConfirm.tool.name, toolUseConfirm.tool.isMcp], ) return ( {userFacingName}( {toolUseConfirm.tool.renderToolUseMessage( toolUseConfirm.input as never, { theme, verbose: true }, )} ) {originalUserFacingName.endsWith(' (MCP)') ? ( (MCP) ) : ( '' )} {truncateToLines(toolUseConfirm.description, 3)} ) }