(
file_path: &Path,
project_root: &Path,
)
| 482 | } |
| 483 | |
| 484 | async fn resolve_instruction_prompts( |
| 485 | file_path: &Path, |
| 486 | project_root: &Path, |
| 487 | ) -> Vec<InstructionPrompt> { |
| 488 | let mut results = Vec::new(); |
| 489 | |
| 490 | let target = file_path |
| 491 | .canonicalize() |
| 492 | .unwrap_or_else(|_| file_path.to_path_buf()); |
| 493 | let root = project_root |
| 494 | .canonicalize() |
| 495 | .unwrap_or_else(|_| project_root.to_path_buf()); |
| 496 | |
| 497 | let mut current = target.parent().unwrap_or(&target).to_path_buf(); |
| 498 | |
| 499 | while current.starts_with(&root) && current != root { |
| 500 | if let Some(found) = find_instruction_file(¤t).await { |
| 501 | let canonical = found.canonicalize().unwrap_or_else(|_| found.clone()); |
| 502 | if canonical != target { |
| 503 | if let Ok(content) = tokio::fs::read_to_string(&found).await { |
| 504 | if !content.is_empty() { |
| 505 | results.push(InstructionPrompt { |
| 506 | filepath: found.to_string_lossy().to_string(), |
| 507 | content: format!("Instructions from: {}\n{}", found.display(), content), |
| 508 | }); |
| 509 | } |
| 510 | } |
| 511 | } |
| 512 | } |
| 513 | |
| 514 | if !current.pop() { |
| 515 | break; |
| 516 | } |
| 517 | } |
| 518 | |
| 519 | if let Some(found) = find_instruction_file(&root).await { |
| 520 | let canonical = found.canonicalize().unwrap_or_else(|_| found.clone()); |
| 521 | if canonical != target { |
| 522 | if let Ok(content) = tokio::fs::read_to_string(&found).await { |
| 523 | if !content.is_empty() { |
| 524 | results.push(InstructionPrompt { |
| 525 | filepath: found.to_string_lossy().to_string(), |
| 526 | content: format!("Instructions from: {}\n{}", found.display(), content), |
| 527 | }); |
| 528 | } |
| 529 | } |
| 530 | } |
| 531 | } |
| 532 | |
| 533 | results |
| 534 | } |
| 535 | |
| 536 | async fn find_instruction_file(dir: &Path) -> Option<PathBuf> { |
| 537 | for name in INSTRUCTION_FILES { |
no test coverage detected