| 213 | |
| 214 | |
| 215 | def load_config(path: Optional[Path], preset_override: Optional[str]) -> Tuple[Dict[str, object], List[RepoSpec]]: |
| 216 | cfg: Dict[str, object] = {} |
| 217 | if path and path.exists(): |
| 218 | cfg = json.loads(path.read_text(encoding="utf-8")) |
| 219 | preset = preset_override if preset_override is not None else str(cfg.get("preset", "none" if cfg.get("repos") else "starter")) |
| 220 | specs: List[RepoSpec] = [] |
| 221 | if preset and preset != "none": |
| 222 | specs.extend(load_curated(preset)) |
| 223 | for item in cfg.get("repos", []) or []: |
| 224 | if isinstance(item, str): |
| 225 | specs.append(RepoSpec(url=item, tags=[])) |
| 226 | elif isinstance(item, dict) and item.get("url"): |
| 227 | specs.append(RepoSpec( |
| 228 | url=str(item["url"]), |
| 229 | tags=list(item.get("tags", [])), |
| 230 | name=item.get("name"), |
| 231 | max_files=item.get("maxFiles"), |
| 232 | max_snippets=item.get("maxSnippets"), |
| 233 | )) |
| 234 | # Stable de-dupe by URL. |
| 235 | seen = set() |
| 236 | unique = [] |
| 237 | for spec in specs: |
| 238 | if spec.url in seen: |
| 239 | continue |
| 240 | seen.add(spec.url) |
| 241 | unique.append(spec) |
| 242 | return cfg, unique |
| 243 | |
| 244 | |
| 245 | def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace: |