( toolName: string, decisionReason?: PermissionDecisionReason, )
| 139 | * Creates a permission request message that explain the permission request |
| 140 | */ |
| 141 | export function createPermissionRequestMessage( |
| 142 | toolName: string, |
| 143 | decisionReason?: PermissionDecisionReason, |
| 144 | ): string { |
| 145 | // Handle different decision reason types |
| 146 | if (decisionReason) { |
| 147 | if ( |
| 148 | (feature('BASH_CLASSIFIER') || feature('TRANSCRIPT_CLASSIFIER')) && |
| 149 | decisionReason.type === 'classifier' |
| 150 | ) { |
| 151 | return `Classifier '${decisionReason.classifier}' requires approval for this ${toolName} command: ${decisionReason.reason}` |
| 152 | } |
| 153 | switch (decisionReason.type) { |
| 154 | case 'hook': { |
| 155 | const hookMessage = decisionReason.reason |
| 156 | ? `Hook '${decisionReason.hookName}' blocked this action: ${decisionReason.reason}` |
| 157 | : `Hook '${decisionReason.hookName}' requires approval for this ${toolName} command` |
| 158 | return hookMessage |
| 159 | } |
| 160 | case 'rule': { |
| 161 | const ruleString = permissionRuleValueToString( |
| 162 | decisionReason.rule.ruleValue, |
| 163 | ) |
| 164 | const sourceString = permissionRuleSourceDisplayString( |
| 165 | decisionReason.rule.source, |
| 166 | ) |
| 167 | return `Permission rule '${ruleString}' from ${sourceString} requires approval for this ${toolName} command` |
| 168 | } |
| 169 | case 'subcommandResults': { |
| 170 | const needsApproval: string[] = [] |
| 171 | for (const [cmd, result] of decisionReason.reasons) { |
| 172 | if (result.behavior === 'ask' || result.behavior === 'passthrough') { |
| 173 | // Strip output redirections for display to avoid showing filenames as commands |
| 174 | // Only do this for Bash tool to avoid affecting other tools |
| 175 | if (toolName === 'Bash') { |
| 176 | const { commandWithoutRedirections, redirections } = |
| 177 | extractOutputRedirections(cmd) |
| 178 | // Only use stripped version if there were actual redirections |
| 179 | const displayCmd = |
| 180 | redirections.length > 0 ? commandWithoutRedirections : cmd |
| 181 | needsApproval.push(displayCmd) |
| 182 | } else { |
| 183 | needsApproval.push(cmd) |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | if (needsApproval.length > 0) { |
| 188 | const n = needsApproval.length |
| 189 | return `This ${toolName} command contains multiple operations. The following ${plural(n, 'part')} ${plural(n, 'requires', 'require')} approval: ${needsApproval.join(', ')}` |
| 190 | } |
| 191 | return `This ${toolName} command contains multiple operations that require approval` |
| 192 | } |
| 193 | case 'permissionPromptTool': |
| 194 | return `Tool '${decisionReason.permissionPromptToolName}' requires approval for this ${toolName} command` |
| 195 | case 'sandboxOverride': |
| 196 | return 'Run outside of the sandbox' |
| 197 | case 'workingDir': |
| 198 | return decisionReason.reason |
no test coverage detected