Generate a lightweight map of the project (symbols, classes, imports).
(cwd: str = None)
| 32 | _repo_map_cwd: str = "" |
| 33 | |
| 34 | def get_repo_map(cwd: str = None) -> str: |
| 35 | """Generate a lightweight map of the project (symbols, classes, imports).""" |
| 36 | global _repo_map_cache, _repo_map_cwd |
| 37 | from core.context import is_ignored |
| 38 | cwd = Path(cwd or os.getcwd()) |
| 39 | cwd_str = str(cwd) |
| 40 | if cwd_str == _repo_map_cwd and _repo_map_cache is not None: |
| 41 | return _repo_map_cache |
| 42 | |
| 43 | # Only scan these extensions |
| 44 | map_exts = {".py", ".js", ".ts", ".c", ".cpp", ".rs", ".go"} |
| 45 | |
| 46 | # Heuristic for symbols |
| 47 | patterns = [ |
| 48 | r"^class\s+(\w+)", |
| 49 | r"^def\s+(\w+)", |
| 50 | r"^function\s+(\w+)", |
| 51 | r"^async\s+def\s+(\w+)", |
| 52 | r"^export\s+(?:async\s+)?(?:function|class)\s+(\w+)", |
| 53 | r"^(?:import|from)\s+[\w.]+", |
| 54 | ] |
| 55 | import re |
| 56 | |
| 57 | repo_map = [] |
| 58 | |
| 59 | # Limit to first 50 relevant files to keep it fast |
| 60 | try: |
| 61 | files = sorted([ |
| 62 | f for f in cwd.rglob("*") |
| 63 | if f.is_file() |
| 64 | and f.suffix in map_exts |
| 65 | and not is_ignored(f) |
| 66 | ])[:50] |
| 67 | except Exception: |
| 68 | return "" |
| 69 | |
| 70 | for f in files: |
| 71 | rel = f.relative_to(cwd) |
| 72 | try: |
| 73 | content = f.read_text(encoding="utf-8", errors="replace") |
| 74 | symbols = [] |
| 75 | for line in content.splitlines(): |
| 76 | line = line.strip() |
| 77 | if any(re.search(p, line) for p in patterns): |
| 78 | # Clean up the line for the map |
| 79 | symbols.append(line[:80]) |
| 80 | if symbols: |
| 81 | repo_map.append(f"📄 {rel}:\n " + "\n ".join(symbols[:15])) |
| 82 | except Exception: |
| 83 | continue |
| 84 | |
| 85 | if not repo_map: |
| 86 | _repo_map_cache = "" |
| 87 | _repo_map_cwd = cwd_str |
| 88 | return "" |
| 89 | |
| 90 | result = "## Project Map\n" + "\n\n".join(repo_map) |
| 91 | # Cap at ~1200 chars (~300 tokens) to avoid bloating the system prompt |
no test coverage detected