(command: string)
| 264 | } |
| 265 | |
| 266 | function suggestionForExactCommand(command: string): PermissionUpdate[] { |
| 267 | // Heredoc commands contain multi-line content that changes each invocation, |
| 268 | // making exact-match rules useless (they'll never match again). Extract a |
| 269 | // stable prefix before the heredoc operator and suggest a prefix rule instead. |
| 270 | const heredocPrefix = extractPrefixBeforeHeredoc(command) |
| 271 | if (heredocPrefix) { |
| 272 | return sharedSuggestionForPrefix(BashTool.name, heredocPrefix) |
| 273 | } |
| 274 | |
| 275 | // Multiline commands without heredoc also make poor exact-match rules. |
| 276 | // Saving the full multiline text can produce patterns containing `:*` in |
| 277 | // the middle, which fails permission validation and corrupts the settings |
| 278 | // file. Use the first line as a prefix rule instead. |
| 279 | if (command.includes('\n')) { |
| 280 | const firstLine = command.split('\n')[0]!.trim() |
| 281 | if (firstLine) { |
| 282 | return sharedSuggestionForPrefix(BashTool.name, firstLine) |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | // Single-line commands: extract a 2-word prefix for reusable rules. |
| 287 | // Without this, exact-match rules are saved that never match future |
| 288 | // invocations with different arguments. |
| 289 | const prefix = getSimpleCommandPrefix(command) |
| 290 | if (prefix) { |
| 291 | return sharedSuggestionForPrefix(BashTool.name, prefix) |
| 292 | } |
| 293 | |
| 294 | return sharedSuggestionForExactCommand(BashTool.name, command) |
| 295 | } |
| 296 | |
| 297 | /** |
| 298 | * If the command contains a heredoc (<<), extract the command prefix before it. |
no test coverage detected