| 822 | |
| 823 | |
| 824 | def find_cpp_algo_binary(search_root: Path) -> Path | None: |
| 825 | preferred_names = ( |
| 826 | ["cpp-algo.exe", "cpp-algo"] if OS_KEYWORD == "win" else ["cpp-algo", "cpp-algo.exe"] |
| 827 | ) |
| 828 | candidates: list[Path] = [] |
| 829 | for name in preferred_names: |
| 830 | candidates.extend(path for path in search_root.rglob(name) if path.is_file()) |
| 831 | |
| 832 | if not candidates: |
| 833 | return None |
| 834 | |
| 835 | def _arch_rank(path_parts: list[str]) -> int: |
| 836 | joined_path = "/".join(path_parts) |
| 837 | preferred_hints = set(ARCH_VARIANT_HINTS.get(ARCH_KEYWORD, ())) |
| 838 | all_hints = {hint for hints in ARCH_VARIANT_HINTS.values() for hint in hints} |
| 839 | has_preferred_arch = any(hint in joined_path for hint in preferred_hints) |
| 840 | has_other_arch = any(hint in joined_path for hint in (all_hints - preferred_hints)) |
| 841 | if has_preferred_arch: |
| 842 | return 0 |
| 843 | if has_other_arch: |
| 844 | return 2 |
| 845 | return 1 |
| 846 | |
| 847 | def _score(path: Path) -> tuple[int, int, int, int]: |
| 848 | path_parts = [part.lower() for part in path.parts] |
| 849 | in_agent_dir = "agent" in path_parts |
| 850 | agent_dir_rank = 0 if in_agent_dir else 1 |
| 851 | preferred_name_rank = 0 if path.name.lower() == preferred_names[0] else 1 |
| 852 | return agent_dir_rank, preferred_name_rank, _arch_rank(path_parts), len(path_parts) |
| 853 | |
| 854 | candidates.sort(key=_score) |
| 855 | return candidates[0] |
| 856 | |
| 857 | |
| 858 | def _replace_file_with_retry(src_path: Path, target_path: Path) -> None: |