diff --git a/src/cascadingdev/setup_project.py b/src/cascadingdev/setup_project.py index 8a5149e..65277cf 100644 --- a/src/cascadingdev/setup_project.py +++ b/src/cascadingdev/setup_project.py @@ -21,6 +21,8 @@ import subprocess import shutil from pathlib import Path +import yaml + # Bundle root (must contain assets/, ramble.py, VERSION) INSTALL_ROOT = Path(__file__).resolve().parent if not (INSTALL_ROOT / "assets").exists(): @@ -148,7 +150,29 @@ def install_precommit_hook(target: Path): say(f"[+] Installed git hook → {hook_dst}") -def run_ramble_and_collect(target: Path, provider: str = "mock", claude_cmd: str = "claude"): +def load_ramble_provider_config() -> tuple[list[str], str, dict[str, dict[str, str]]]: + providers: dict[str, dict[str, str]] = {"mock": {"kind": "mock"}} + default = "mock" + config_path = INSTALL_ROOT / "config" / "ai.yml" + if config_path.exists(): + try: + data = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {} + ramble = data.get("ramble") if isinstance(data, dict) else {} + if isinstance(ramble, dict): + if isinstance(ramble.get("providers"), dict): + providers.update({k: v for k, v in ramble["providers"].items() if isinstance(v, dict)}) + dp = ramble.get("default_provider") + if isinstance(dp, str) and dp.strip(): + default = dp.strip() + except Exception: + pass + choices = sorted(providers.keys()) + if default not in choices: + default = "mock" + return choices, default, providers + + +def run_ramble_and_collect(target: Path, provider: str = "mock", provider_meta: dict[str, str] | None = None): """ Launch Ramble GUI to collect initial feature request details. Falls back to terminal prompts if GUI fails or returns invalid JSON. @@ -171,7 +195,6 @@ def run_ramble_and_collect(target: Path, provider: str = "mock", claude_cmd: str args = [ sys.executable, str(ramble), "--provider", provider, - "--claude-cmd", claude_cmd, "--prompt", "Describe your initial feature request for this repository", "--fields", *field_names, ] @@ -363,11 +386,12 @@ def first_commit(target: Path): def main(): """Main entry point for the Cascading Development setup script.""" # Parse command line arguments + provider_choices, default_provider, provider_map = load_ramble_provider_config() + ap = argparse.ArgumentParser() ap.add_argument("--target", help="Destination path to create/use the repo") - ap.add_argument("--provider", choices=["mock", "claude"], default="mock", help="Ramble provider (default: mock)") + ap.add_argument("--provider", choices=provider_choices, default=default_provider, help="Ramble provider (default from config)") ap.add_argument("--no-ramble", action="store_true", help="Skip launching Ramble") - ap.add_argument("--claude-cmd", default="claude") args = ap.parse_args() # Get target directory from args or prompt user @@ -409,7 +433,7 @@ def main(): # Step 5: Launch Ramble (if available and not disabled) req = None if not args.no_ramble: - req = run_ramble_and_collect(target, provider=args.provider, claude_cmd=args.claude_cmd) + req = run_ramble_and_collect(target, provider=args.provider, provider_meta=provider_map.get(args.provider)) # Step 6: Seed first feature based on Ramble output seed_initial_feature(target, req)