Instructions to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M # Run inference directly in the terminal: llama cli -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M # Run inference directly in the terminal: llama cli -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
Use Docker
docker model run hf.co/aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "aogavrilov/diffusiongemma-agent-iq3-cuda13" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "aogavrilov/diffusiongemma-agent-iq3-cuda13", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
- Ollama
How to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with Ollama:
ollama run hf.co/aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
- Unsloth Studio
How to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for aogavrilov/diffusiongemma-agent-iq3-cuda13 to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for aogavrilov/diffusiongemma-agent-iq3-cuda13 to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for aogavrilov/diffusiongemma-agent-iq3-cuda13 to start chatting
- Pi
How to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @mariozechner/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Hermes Agent new
How to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
Run Hermes
hermes
- Atomic Chat new
- OpenClaw new
How to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
- Docker Model Runner
How to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with Docker Model Runner:
docker model run hf.co/aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
- Lemonade
How to use aogavrilov/diffusiongemma-agent-iq3-cuda13 with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull aogavrilov/diffusiongemma-agent-iq3-cuda13:Q4_K_M
Run and chat with the model
lemonade run user.diffusiongemma-agent-iq3-cuda13-Q4_K_M
List all available models
lemonade list
| #!/usr/bin/env python3 | |
| """Checkpointed controller for bounded DG coding sessions. | |
| The controller never asks DiffusionGemma to choose or execute shell commands. | |
| It delegates retrieval to Haystack BM25 and code changes to the existing | |
| session/Aider path, while preserving all state and test feedback between | |
| bounded retries. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import hashlib | |
| import json | |
| import os | |
| import re | |
| import subprocess | |
| import sys | |
| import tempfile | |
| import time | |
| import urllib.error | |
| import urllib.request | |
| from pathlib import Path | |
| from typing import Any | |
| DG_ROOT = Path(__file__).resolve().parents[1] | |
| DEFAULT_STATE_ROOT = DG_ROOT / "runlogs" / "dg-autonomous-supervisor" | |
| STATE_VERSION = 1 | |
| def now() -> float: | |
| return time.time() | |
| def slug(value: str, limit: int = 48) -> str: | |
| text = re.sub(r"[^A-Za-z0-9]+", "-", value.lower()).strip("-") | |
| return text[:limit] or "task" | |
| def atomic_write_json(path: Path, data: dict[str, Any]) -> None: | |
| path.parent.mkdir(parents=True, exist_ok=True) | |
| with tempfile.NamedTemporaryFile("w", encoding="utf-8", delete=False, dir=path.parent, suffix=".tmp") as handle: | |
| json.dump(data, handle, ensure_ascii=False, indent=2) | |
| handle.write("\n") | |
| temp = Path(handle.name) | |
| temp.replace(path) | |
| def read_json(path: Path) -> dict[str, Any] | None: | |
| try: | |
| data = json.loads(path.read_text(encoding="utf-8")) | |
| except (OSError, ValueError): | |
| return None | |
| return data if isinstance(data, dict) else None | |
| def git(repo: Path, *args: str, input_text: str | None = None) -> subprocess.CompletedProcess[str]: | |
| return subprocess.run( | |
| ["git", *args], | |
| cwd=repo, | |
| input=input_text, | |
| text=True, | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.PIPE, | |
| check=False, | |
| ) | |
| def git_status(repo: Path) -> str: | |
| return git(repo, "status", "--short").stdout | |
| def git_snapshot(repo: Path) -> dict[str, str]: | |
| return { | |
| "status": git_status(repo), | |
| "diff": git(repo, "diff", "--binary", "--", ".").stdout, | |
| "cached_diff": git(repo, "diff", "--cached", "--binary", "--", ".").stdout, | |
| "head": git(repo, "rev-parse", "HEAD").stdout.strip(), | |
| } | |
| def wsl_path(path: Path) -> str: | |
| raw = str(path.resolve()) | |
| if os.name != "nt": | |
| return raw | |
| match = re.match(r"^([A-Za-z]):\\(.*)$", raw) | |
| if not match: | |
| return raw | |
| drive, tail = match.groups() | |
| return f"/mnt/{drive.lower()}/{tail.replace(chr(92), '/') }" | |
| def haystack_command(repo: Path, task: str, index_dir: Path, rebuild: bool) -> list[str]: | |
| runner = DG_ROOT / "scripts" / "dg_haystack_runner.py" | |
| if os.name == "nt": | |
| linux_python = wsl_path(DG_ROOT / ".venv-haystack" / "bin" / "python") | |
| command = [ | |
| "wsl.exe", | |
| "--exec", | |
| linux_python, | |
| wsl_path(runner), | |
| "--repo", | |
| wsl_path(repo), | |
| "--task", | |
| task, | |
| "--retrieve-only", | |
| "--json", | |
| "--index-dir", | |
| wsl_path(index_dir), | |
| ] | |
| else: | |
| python = Path(os.environ.get("DG_HAYSTACK_PYTHON", DG_ROOT / ".venv-haystack" / "bin" / "python")) | |
| command = [ | |
| str(python), | |
| str(runner), | |
| "--repo", | |
| str(repo), | |
| "--task", | |
| task, | |
| "--retrieve-only", | |
| "--json", | |
| "--index-dir", | |
| str(index_dir), | |
| ] | |
| if rebuild: | |
| command.append("--rebuild-index") | |
| return command | |
| def run_retrieval(repo: Path, task: str, index_dir: Path, rebuild: bool, timeout: int) -> tuple[dict[str, Any], int]: | |
| command = haystack_command(repo, task, index_dir, rebuild) | |
| try: | |
| proc = subprocess.run(command, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False, timeout=timeout) | |
| except (OSError, subprocess.TimeoutExpired) as exc: | |
| return {"status": "failed", "error": str(exc), "command": command}, 1 | |
| try: | |
| payload = json.loads(proc.stdout) | |
| except ValueError: | |
| payload = {"status": "failed", "stdout_tail": proc.stdout[-4000:], "stderr_tail": proc.stderr[-4000:]} | |
| if not isinstance(payload, dict): | |
| payload = {"status": "failed", "error": "Haystack did not return a JSON object"} | |
| payload["command"] = command | |
| payload["returncode"] = proc.returncode | |
| if proc.stderr: | |
| payload["stderr_tail"] = proc.stderr[-4000:] | |
| return payload, proc.returncode | |
| def planner_guidance(args: argparse.Namespace, retrieval: dict[str, Any]) -> dict[str, Any]: | |
| """Optional planner is advisory: it cannot execute commands or modify files.""" | |
| if not args.planner_url or not args.planner_model: | |
| return {"status": "disabled"} | |
| paths = retrieval.get("retrieval", {}).get("paths", []) if isinstance(retrieval.get("retrieval"), dict) else [] | |
| prompt = "Give concise file-level coding guidance. Do not emit shell commands or patches. Existing paths: " + ", ".join(map(str, paths)) + "\nTask: " + args.task | |
| request = urllib.request.Request( | |
| args.planner_url.rstrip("/") + "/chat/completions", | |
| data=json.dumps({"model": args.planner_model, "messages": [{"role": "user", "content": prompt}], "temperature": 0}).encode("utf-8"), | |
| headers={"Content-Type": "application/json", "Authorization": f"Bearer {args.planner_api_key or 'dummy'}"}, | |
| method="POST", | |
| ) | |
| try: | |
| with urllib.request.urlopen(request, timeout=args.planner_timeout) as response: | |
| payload = json.loads(response.read().decode("utf-8")) | |
| return {"status": "success", "model": args.planner_model, "guidance": str(payload["choices"][0]["message"]["content"]).strip()[:2400]} | |
| except (KeyError, TypeError, ValueError, urllib.error.URLError, TimeoutError) as exc: | |
| return {"status": "failed", "model": args.planner_model, "error": str(exc)} | |
| def state_dir_for(args: argparse.Namespace, repo: Path) -> Path: | |
| if args.state_dir: | |
| return Path(args.state_dir).resolve() | |
| digest = hashlib.sha256(f"{repo}\0{args.task}".encode("utf-8")).hexdigest()[:12] | |
| return DEFAULT_STATE_ROOT / f"{time.strftime('%Y%m%d-%H%M%S')}-{slug(args.task)}-{digest}" | |
| def initial_state(args: argparse.Namespace, repo: Path, state_dir: Path) -> dict[str, Any]: | |
| return { | |
| "version": STATE_VERSION, | |
| "repo": str(repo), | |
| "task": args.task, | |
| "state_dir": str(state_dir), | |
| "created_at": now(), | |
| "updated_at": now(), | |
| "status": "created", | |
| "max_steps": args.max_steps, | |
| "initial_git": git_snapshot(repo), | |
| "retrieval": {}, | |
| "planner": {"status": "not-run"}, | |
| "steps": [], | |
| "rollback": {"attempted": False, "status": "not-needed"}, | |
| "warnings": [], | |
| } | |
| def write_state(state_dir: Path, state: dict[str, Any]) -> None: | |
| state["updated_at"] = now() | |
| atomic_write_json(state_dir / "state.json", state) | |
| retrieval = state.get("retrieval") if isinstance(state.get("retrieval"), dict) else {} | |
| lines = [ | |
| "# DG Persistent Supervisor", | |
| "", | |
| f"- Status: `{state.get('status')}`", | |
| f"- Repository: `{state.get('repo')}`", | |
| f"- Task: {state.get('task')}", | |
| f"- Steps: `{len(state.get('steps', []))}/{state.get('max_steps')}`", | |
| ] | |
| paths = retrieval.get("retrieval", {}).get("paths", []) if isinstance(retrieval.get("retrieval"), dict) else [] | |
| if paths: | |
| lines.extend(["", "## Retrieved Files", *[f"- `{item}`" for item in paths]]) | |
| if state.get("steps"): | |
| lines.extend(["", "## Attempts"]) | |
| for item in state["steps"]: | |
| lines.append(f"- Step {item.get('index')}: `{item.get('status')}` ({item.get('session_dir', '')})") | |
| if state.get("warnings"): | |
| lines.extend(["", "## Warnings", *[f"- {item}" for item in state["warnings"]]]) | |
| (state_dir / "SUMMARY.md").write_text("\n".join(lines) + "\n", encoding="utf-8") | |
| def feedback_from_session(session: dict[str, Any], limit: int = 1800) -> str: | |
| artifacts = session.get("artifacts") if isinstance(session.get("artifacts"), dict) else {} | |
| parts: list[str] = [] | |
| for key in ("verify_report", "task_stderr", "task_stdout"): | |
| path = Path(str(artifacts.get(key) or "")) | |
| if not path.is_file(): | |
| continue | |
| text = path.read_text(encoding="utf-8", errors="replace").strip() | |
| if text: | |
| parts.append(text[-limit:]) | |
| return "\n\n".join(parts)[-limit:] | |
| def session_command(args: argparse.Namespace, repo: Path, state_dir: Path, step: int, retrieval: dict[str, Any], feedback: str, planner: dict[str, Any]) -> list[str]: | |
| task = args.task | |
| stats = retrieval.get("retrieval") if isinstance(retrieval.get("retrieval"), dict) else {} | |
| paths = stats.get("paths") if isinstance(stats.get("paths"), list) else [] | |
| if paths: | |
| task += "\n\nSupervisor retrieval candidates: " + ", ".join(str(item) for item in paths[: args.max_files]) | |
| if feedback: | |
| task += "\n\nPrevious verified attempt failed. Keep the task scope unchanged and use this test feedback:\n" + feedback[-1800:] | |
| if planner.get("status") == "success": | |
| task += "\n\nExternal planner guidance (advisory only; verify against repository):\n" + str(planner.get("guidance") or "") | |
| command = [ | |
| sys.executable, | |
| str(DG_ROOT / "scripts" / "dg_agent.py"), | |
| "session", | |
| "--repo", | |
| str(repo), | |
| "--task", | |
| task, | |
| "--out-dir", | |
| str(state_dir / "sessions"), | |
| "--max-files", | |
| str(args.max_files), | |
| "--max-snippet-chars", | |
| str(args.max_snippet_chars), | |
| "--test-timeout", | |
| str(args.test_timeout), | |
| "--aider-timeout", | |
| str(args.aider_timeout), | |
| "--repair-attempts", | |
| str(args.repair_attempts), | |
| "--wall-timeout", | |
| str(args.wall_timeout), | |
| "--rollback-on-failure", | |
| ] | |
| for file_name in args.file: | |
| command.extend(["--file", file_name]) | |
| if args.test_cmd: | |
| command.extend(["--test-cmd", args.test_cmd]) | |
| if args.auto_test: | |
| command.append("--auto-test") | |
| if args.no_deterministic_first: | |
| command.append("--no-deterministic-first") | |
| if args.dry_run: | |
| command.append("--dry-run") | |
| return command | |
| def latest_session(sessions_dir: Path) -> dict[str, Any] | None: | |
| candidates = sorted(sessions_dir.glob("*/session.json"), key=lambda item: item.stat().st_mtime, reverse=True) | |
| return read_json(candidates[0]) if candidates else None | |
| def rollback_clean_start(repo: Path, state_dir: Path, initial: dict[str, Any]) -> dict[str, Any]: | |
| if str(initial.get("status") or "").strip(): | |
| return {"attempted": False, "status": "skipped", "reason": "repository was dirty before the run"} | |
| status = git_status(repo) | |
| if not status.strip(): | |
| return {"attempted": False, "status": "not-needed"} | |
| if any(line.startswith("??") for line in status.splitlines()): | |
| return {"attempted": False, "status": "blocked", "reason": "unexpected untracked files; refusing to remove them", "status_after": status} | |
| patch = git(repo, "diff", "--binary", "--", ".").stdout | |
| if not patch: | |
| return {"attempted": False, "status": "blocked", "reason": "staged or non-diff changes remain", "status_after": status} | |
| snapshot = state_dir / "unexpected-failure.diff" | |
| snapshot.write_text(patch, encoding="utf-8") | |
| proc = git(repo, "apply", "--reverse", "--whitespace=nowarn", input_text=patch) | |
| return { | |
| "attempted": True, | |
| "status": "success" if proc.returncode == 0 and not git_status(repo).strip() else "failed", | |
| "patch": str(snapshot), | |
| "stderr": proc.stderr[-2000:], | |
| "status_after": git_status(repo), | |
| } | |
| def run(args: argparse.Namespace) -> int: | |
| repo = Path(args.repo).resolve() | |
| if not repo.is_dir(): | |
| print(f"repo does not exist: {repo}", file=sys.stderr) | |
| return 2 | |
| if git(repo, "rev-parse", "--is-inside-work-tree").stdout.strip() != "true": | |
| print(f"repo is not a git repository: {repo}", file=sys.stderr) | |
| return 2 | |
| if not 1 <= args.max_steps <= 5: | |
| print("--max-steps must be between 1 and 5", file=sys.stderr) | |
| return 2 | |
| state_dir = state_dir_for(args, repo) | |
| state_path = state_dir / "state.json" | |
| state = read_json(state_path) if args.resume or args.status else None | |
| if args.status: | |
| if state is None: | |
| print(f"state is missing: {state_path}", file=sys.stderr) | |
| return 2 | |
| print(json.dumps(state, ensure_ascii=False, indent=2) if args.json else f"{state.get('status')} {state_path}") | |
| return 0 | |
| if state is None: | |
| if state_path.exists(): | |
| print(f"state already exists: {state_dir}; pass --resume to continue it", file=sys.stderr) | |
| return 2 | |
| state_dir.mkdir(parents=True, exist_ok=False) | |
| state = initial_state(args, repo, state_dir) | |
| if str(state["initial_git"].get("status") or "").strip() and not args.allow_dirty: | |
| state["status"] = "blocked" | |
| state["warnings"].append("repository is dirty; use --allow-dirty to run without controller rollback") | |
| write_state(state_dir, state) | |
| print(f"Supervisor state: {state_path}") | |
| return 3 | |
| if args.allow_dirty: | |
| state["warnings"].append("started from a dirty repository; controller rollback is disabled") | |
| elif state.get("status") == "success": | |
| print(json.dumps(state, ensure_ascii=False, indent=2) if args.json else f"Supervisor already succeeded: {state_path}") | |
| return 0 | |
| index_dir = Path(args.index_dir).resolve() if args.index_dir else (DG_ROOT / "runlogs" / "dg-retrieval-index" / hashlib.sha256(str(repo).encode("utf-8")).hexdigest()[:16]) | |
| retrieval, retrieval_rc = run_retrieval(repo, args.task, index_dir, args.rebuild_index, args.retrieval_timeout) | |
| state["retrieval"] = retrieval | |
| (state_dir / "retrieval.json").write_text(json.dumps(retrieval, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") | |
| if retrieval_rc != 0 or retrieval.get("status") != "success": | |
| state["status"] = "blocked" | |
| state["warnings"].append("Haystack retrieval failed; no edit was attempted") | |
| write_state(state_dir, state) | |
| print(f"Supervisor state: {state_path}") | |
| return 1 | |
| planner = planner_guidance(args, retrieval) | |
| state["planner"] = planner | |
| if planner.get("status") == "failed": | |
| state["warnings"].append("external planner failed; continuing without planner guidance") | |
| write_state(state_dir, state) | |
| start_index = len(state.get("steps", [])) + 1 | |
| feedback = "" | |
| if state.get("steps"): | |
| previous = state["steps"][-1] | |
| feedback = str(previous.get("feedback") or "") | |
| for index in range(start_index, args.max_steps + 1): | |
| before = git_snapshot(repo) | |
| checkpoint = state_dir / "checkpoints" / f"{index:02d}-before.json" | |
| checkpoint.parent.mkdir(parents=True, exist_ok=True) | |
| checkpoint.write_text(json.dumps(before, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") | |
| command = session_command(args, repo, state_dir, index, retrieval, feedback, planner) | |
| if args.dry_run: | |
| attempt = {"index": index, "status": "dry-run", "command": command, "checkpoint": str(checkpoint)} | |
| state["steps"].append(attempt) | |
| state["status"] = "dry-run" | |
| write_state(state_dir, state) | |
| break | |
| try: | |
| proc = subprocess.run(command, cwd=DG_ROOT, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False, timeout=args.wall_timeout + 30) | |
| except subprocess.TimeoutExpired as exc: | |
| proc = subprocess.CompletedProcess(command, 124, stdout="", stderr=f"controller timed out after {exc.timeout}s") | |
| session = latest_session(state_dir / "sessions") or {} | |
| feedback = feedback_from_session(session) | |
| attempt = { | |
| "index": index, | |
| "status": "success" if proc.returncode == 0 and session.get("status") == "success" else "failed", | |
| "returncode": proc.returncode, | |
| "command": command, | |
| "checkpoint": str(checkpoint), | |
| "session_dir": str(session.get("session_dir") or ""), | |
| "session_report": session, | |
| "feedback": feedback, | |
| "stdout_tail": proc.stdout[-4000:], | |
| "stderr_tail": proc.stderr[-4000:], | |
| } | |
| state["steps"].append(attempt) | |
| if attempt["status"] == "success": | |
| state["status"] = "success" | |
| state["rollback"] = {"attempted": False, "status": "not-needed"} | |
| write_state(state_dir, state) | |
| break | |
| if not args.allow_dirty: | |
| rollback = rollback_clean_start(repo, state_dir, state["initial_git"]) | |
| state["rollback"] = rollback | |
| if rollback.get("status") == "blocked": | |
| state["status"] = "blocked" | |
| state["warnings"].append("unexpected repository state after failed session") | |
| write_state(state_dir, state) | |
| break | |
| state["status"] = "retrying" if index < args.max_steps else "failed" | |
| write_state(state_dir, state) | |
| write_state(state_dir, state) | |
| result = {"status": state.get("status"), "state_dir": str(state_dir), "state": str(state_path), "steps": len(state.get("steps", []))} | |
| print(json.dumps(result, ensure_ascii=False, indent=2) if args.json else f"Supervisor status: {result['status']}\nSupervisor state: {state_path}") | |
| return 0 if state.get("status") == "success" else 1 | |
| def parse_args() -> argparse.Namespace: | |
| parser = argparse.ArgumentParser(description="Run a checkpointed persistent controller over Haystack retrieval and DG sessions.") | |
| parser.add_argument("--repo", required=True) | |
| parser.add_argument("--task", required=True) | |
| parser.add_argument("--file", action="append", default=[]) | |
| parser.add_argument("--state-dir", default="") | |
| parser.add_argument("--resume", action="store_true") | |
| parser.add_argument("--status", action="store_true") | |
| parser.add_argument("--index-dir", default="") | |
| parser.add_argument("--rebuild-index", action="store_true") | |
| parser.add_argument("--max-steps", type=int, default=3) | |
| parser.add_argument("--max-files", type=int, default=3) | |
| parser.add_argument("--max-snippet-chars", type=int, default=1200) | |
| parser.add_argument("--test-cmd", default="") | |
| parser.add_argument("--auto-test", action=argparse.BooleanOptionalAction, default=True) | |
| parser.add_argument("--test-timeout", type=int, default=120) | |
| parser.add_argument("--aider-timeout", type=int, default=300) | |
| parser.add_argument("--repair-attempts", type=int, default=1) | |
| parser.add_argument("--wall-timeout", type=int, default=420) | |
| parser.add_argument("--retrieval-timeout", type=int, default=180) | |
| parser.add_argument("--planner-url", default=os.environ.get("DG_PLANNER_URL", ""), help="Optional stronger OpenAI-compatible planner URL") | |
| parser.add_argument("--planner-model", default=os.environ.get("DG_PLANNER_MODEL", "")) | |
| parser.add_argument("--planner-api-key", default=os.environ.get("DG_PLANNER_API_KEY", "")) | |
| parser.add_argument("--planner-timeout", type=int, default=60) | |
| parser.add_argument("--allow-dirty", action="store_true") | |
| parser.add_argument("--no-deterministic-first", action="store_true") | |
| parser.add_argument("--dry-run", action="store_true") | |
| parser.add_argument("--json", action="store_true") | |
| return parser.parse_args() | |
| if __name__ == "__main__": | |
| raise SystemExit(run(parse_args())) | |