(script: string)
| 437 | } |
| 438 | |
| 439 | function detectGrepFileDump(script: string): boolean { |
| 440 | // Fast-path: avoid doing any work if "grep" doesn't appear at all. |
| 441 | if (!script.includes("grep")) { |
| 442 | return false; |
| 443 | } |
| 444 | |
| 445 | const segments = script.split(/\n|&&|\|\||;|\|/); |
| 446 | for (const segment of segments) { |
| 447 | const tokens = segment.trim().split(/\s+/).filter(Boolean); |
| 448 | const grepIndex = getGrepCommandTokenIndex(tokens); |
| 449 | if (grepIndex === null) continue; |
| 450 | |
| 451 | const args = tokens.slice(grepIndex + 1); |
| 452 | if (args.length === 0) continue; |
| 453 | |
| 454 | // Ignore heredocs / here-strings (not a file read). |
| 455 | if (args.some((t) => t.startsWith("<<") || t.startsWith("<<<"))) { |
| 456 | continue; |
| 457 | } |
| 458 | |
| 459 | const { pattern, tokensAfterPattern } = parseSearchCommandArgs("grep", args); |
| 460 | if (!pattern) continue; |
| 461 | |
| 462 | if (!isMatchAllSearchPattern(stripOuterQuotes(pattern))) { |
| 463 | continue; |
| 464 | } |
| 465 | |
| 466 | if (hasFileReadTargetToken(tokensAfterPattern)) { |
| 467 | return true; |
| 468 | } |
| 469 | } |
| 470 | |
| 471 | return false; |
| 472 | } |
| 473 | |
| 474 | type BashToolForegroundResult = Exclude<BashToolResult, { backgroundProcessId: string }>; |
| 475 |
no test coverage detected