({ onDone, commands }: Props)
| 30 | }; |
| 31 | |
| 32 | export function TrustDialog({ onDone, commands }: Props): React.ReactNode { |
| 33 | const { servers: projectServers } = getMcpConfigsByScope('project'); |
| 34 | |
| 35 | // In all cases, we generally check only the project-level and |
| 36 | // project-local-level settings, which we assume that users do not configure |
| 37 | // directly compared to user-level settings. |
| 38 | |
| 39 | // Check for MCPs |
| 40 | const hasMcpServers = Object.keys(projectServers).length > 0; |
| 41 | // Check for hooks |
| 42 | const hooksSettingSources = getHooksSources(); |
| 43 | const hasHooks = hooksSettingSources.length > 0; |
| 44 | // Check whether code execution is allowed in permissions and slash commands |
| 45 | const bashSettingSources = getBashPermissionSources(); |
| 46 | // Check for apiKeyHelper which executes arbitrary commands |
| 47 | const apiKeyHelperSources = getApiKeyHelperSources(); |
| 48 | const hasApiKeyHelper = apiKeyHelperSources.length > 0; |
| 49 | // Check for AWS commands which execute arbitrary commands |
| 50 | const awsCommandsSources = getAwsCommandsSources(); |
| 51 | const hasAwsCommands = awsCommandsSources.length > 0; |
| 52 | // Check for GCP commands which execute arbitrary commands |
| 53 | const gcpCommandsSources = getGcpCommandsSources(); |
| 54 | const hasGcpCommands = gcpCommandsSources.length > 0; |
| 55 | // Check for otelHeadersHelper which executes arbitrary commands |
| 56 | const otelHeadersHelperSources = getOtelHeadersHelperSources(); |
| 57 | const hasOtelHeadersHelper = otelHeadersHelperSources.length > 0; |
| 58 | // Check for dangerous environment variables (not in SAFE_ENV_VARS) |
| 59 | const dangerousEnvVarsSources = getDangerousEnvVarsSources(); |
| 60 | const hasDangerousEnvVars = dangerousEnvVarsSources.length > 0; |
| 61 | |
| 62 | const hasSlashCommandBash = |
| 63 | commands?.some( |
| 64 | command => |
| 65 | command.type === 'prompt' && |
| 66 | command.loadedFrom === 'commands_DEPRECATED' && |
| 67 | (command.source === 'projectSettings' || command.source === 'localSettings') && |
| 68 | command.allowedTools?.some((tool: string) => tool === BASH_TOOL_NAME || tool.startsWith(BASH_TOOL_NAME + '(')), |
| 69 | ) ?? false; |
| 70 | |
| 71 | const hasSkillsBash = |
| 72 | commands?.some( |
| 73 | command => |
| 74 | command.type === 'prompt' && |
| 75 | (command.loadedFrom === 'skills' || command.loadedFrom === 'plugin') && |
| 76 | (command.source === 'projectSettings' || command.source === 'localSettings' || command.source === 'plugin') && |
| 77 | command.allowedTools?.some((tool: string) => tool === BASH_TOOL_NAME || tool.startsWith(BASH_TOOL_NAME + '(')), |
| 78 | ) ?? false; |
| 79 | |
| 80 | const hasAnyBashExecution = bashSettingSources.length > 0 || hasSlashCommandBash || hasSkillsBash; |
| 81 | |
| 82 | const hasTrustDialogAccepted = checkHasTrustDialogAccepted(); |
| 83 | const [pendingExitCode, setPendingExitCode] = React.useState<number | null>(null); |
| 84 | |
| 85 | // When a non-null exit code is set, render null (clear screen) first, |
| 86 | // then trigger shutdown in the next tick so Ink has time to flush |
| 87 | // the empty frame before cleanupTerminalModes() unmounts and exits |
| 88 | // the alt screen. Without this deferral, gracefulShutdownSync starts |
| 89 | // async cleanup immediately after React commit, racing the reconciler |
nothing calls this directly
no test coverage detected