From 7e194c3a1dfc1b07d9d776dbf033097ca31589e2 Mon Sep 17 00:00:00 2001 From: Aakif Nawaz Date: Fri, 24 Jul 2026 20:46:09 +0000 Subject: [PATCH] feat(framework): allow overriding the vLLM repository Keep ROCm/vllm as the default while allowing operators to target an upstream vLLM checkout and PR stream. Signed-off-by: Aakif Nawaz --- .env.template | 4 ++ docs/reference/environment-variables.md | 1 + src/hyperloom/agents/framework/repo_map.py | 69 +++++++++++++++++-- .../agents/framework/tests/test_pr_kb.py | 2 + .../tests/test_framework_agent_authoring.py | 16 +++++ .../tests/test_framework_agent_client_unit.py | 30 +++++++- .../test_framework_agent_discover_directed.py | 21 +++++- .../tests/test_per_domain_prompts.py | 10 +++ .../orchestrator/phases/framework.py | 22 ++++-- .../prompts/specialist_prompt_builder.py | 8 +-- .../orchestrator/specialists/domains.py | 16 +++++ 11 files changed, 182 insertions(+), 17 deletions(-) diff --git a/.env.template b/.env.template index 952bb982d1..8cc78ddbb0 100644 --- a/.env.template +++ b/.env.template @@ -65,6 +65,10 @@ OPENAI_BASE_URL=https:///api/v1/llm-proxy/v1 # Colon-separated list; unioned with defaults (/sgl-workspace/{aiter,sglang,vllm}/). # Populated automatically by src/hyperloom/inference_optimizer/assets/install.sh probe. # INFERENCE_OPTIMIZER_FRAMEWORK_SOURCE_ROOTS= +# +# (Optional) Override the vLLM repository used by framework-agent discovery +# and PR Monitor. Default: AMD's ROCm fork; use upstream when the runtime does. +# HYPERLOOM_VLLM_REPO_URL=https://github.com/vllm-project/vllm.git # Writable artifact root: hosts every session dir, optimizer_runs/, and the # runtime/ tree generated by install.sh (GEAK e2e checkout, diff --git a/docs/reference/environment-variables.md b/docs/reference/environment-variables.md index 1dd63a744a..f9905dc691 100644 --- a/docs/reference/environment-variables.md +++ b/docs/reference/environment-variables.md @@ -206,6 +206,7 @@ The following variables configure framework source discovery and path overrides. | Variable | Default | Description | |---------------------------------------------------|------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| +| `HYPERLOOM_`
`VLLM_REPO_URL` | `https://github.com/ROCm/vllm.git` | Override the vLLM repository used by framework-agent discovery and PR Monitor. For upstream vLLM builds, set `https://github.com/vllm-project/vllm.git`. The built-in ROCm URL remains a recognized origin alias for persisted candidates. | | `INFERENCE_`
`OPTIMIZER_`
`FRAMEWORK_`
`SOURCE_ROOTS` | Union with `/sgl-workspace`
`/{aiter,sglang`
`,vllm}` | Colon-separated list of source roots used by PolicyGate and flag discovery. Populated automatically by `src/hyperloom/inference_optimizer/assets/install.sh`'s `_probe_framework_source_roots` step (using `hyperloom.orchestrator.framework.paths.probe_framework_source_roots_for_env`). | | `INFERENCE_`
`OPTIMIZER`
`_RESCUE_PATHS` | Unset | Colon-separated list of extra directories the harvest step scans for stray `result.json` files written outside the session dir (InferenceX-native scripts that hardcode `--result-dir`). | | `INFERENCE_`
`OPTIMIZER`
`_AITER_JIT_DIR` | Aiter default | Override the aiter just-in-time (JIT) cache root for cold-cap sizing. | diff --git a/src/hyperloom/agents/framework/repo_map.py b/src/hyperloom/agents/framework/repo_map.py index ab3f7f1c5e..d799ceaeda 100644 --- a/src/hyperloom/agents/framework/repo_map.py +++ b/src/hyperloom/agents/framework/repo_map.py @@ -10,6 +10,10 @@ from __future__ import annotations +import os +import re +from urllib.parse import urlsplit + _FRAMEWORK_TO_REPO_URL: dict[str, str] = { "sglang": "https://github.com/sgl-project/sglang.git", "vllm": "https://github.com/ROCm/vllm.git", @@ -17,6 +21,9 @@ "xdit": "https://github.com/xdit-project/xDiT.git", } +VLLM_REPO_URL_ENV = "HYPERLOOM_VLLM_REPO_URL" +_GITHUB_REPO_RE = re.compile(r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$") + # Known framework names, derived from the URL dict. KNOWN_FRAMEWORKS: frozenset[str] = frozenset(_FRAMEWORK_TO_REPO_URL.keys()) @@ -49,10 +56,49 @@ def bridge_repo_urls(bridge_layer: str) -> tuple[str, ...]: return _BRIDGE_LAYER_TO_REPO_URLS.get((bridge_layer or "").strip().lower(), ()) +def canonical_github_repo_url(value: str) -> str: + """Normalize a GitHub repository reference to one HTTPS clone URL.""" + + raw = (value or "").strip() + if not raw: + return "" + if raw.lower().startswith("git@github.com:"): + repo = raw.split(":", 1)[1] + elif "://" in raw: + parsed = urlsplit(raw) + if parsed.hostname is None or parsed.hostname.lower() != "github.com": + raise ValueError(f"repository override must target github.com, got {value!r}") + repo = parsed.path + else: + repo = raw + repo = repo.strip("/") + if repo.lower().endswith(".git"): + repo = repo[:-4] + if not _GITHUB_REPO_RE.fullmatch(repo): + raise ValueError(f"repository override must be OWNER/REPO, got {value!r}") + owner, name = repo.split("/", 1) + return f"https://github.com/{owner}/{name}.git" + + +def github_repo_name(value: str) -> str: + """Return ``OWNER/REPO`` for a valid GitHub repository reference.""" + + canonical = canonical_github_repo_url(value) + return canonical.split("github.com/", 1)[1][:-4] if canonical else "" + + +def default_repo_url_for_framework(framework: str) -> str: + """Return the built-in GitHub repo URL for ``framework``.""" + + return _FRAMEWORK_TO_REPO_URL.get((framework or "").strip().lower(), "") + + def repo_url_for_framework(framework: str) -> str: - """Return the canonical GitHub repo URL for ``framework``. + """Return the effective GitHub repo URL for ``framework``. The lookup is case-insensitive and tolerant of surrounding whitespace. + vLLM operators may override the AMD-fork default with + ``HYPERLOOM_VLLM_REPO_URL``. Args: framework (str): Framework name (e.g. ``"sglang"``, ``"vllm"``, @@ -63,7 +109,20 @@ def repo_url_for_framework(framework: str) -> str: frameworks; the caller is expected to bail out / log when this happens. """ - return _FRAMEWORK_TO_REPO_URL.get((framework or "").strip().lower(), "") - - -__all__ = ["KNOWN_FRAMEWORKS", "bridge_repo_urls", "repo_url_for_framework"] + normalized = (framework or "").strip().lower() + if normalized == "vllm": + override = os.environ.get(VLLM_REPO_URL_ENV, "").strip() + if override: + return canonical_github_repo_url(override) + return default_repo_url_for_framework(normalized) + + +__all__ = [ + "KNOWN_FRAMEWORKS", + "VLLM_REPO_URL_ENV", + "bridge_repo_urls", + "canonical_github_repo_url", + "default_repo_url_for_framework", + "github_repo_name", + "repo_url_for_framework", +] diff --git a/src/hyperloom/agents/framework/tests/test_pr_kb.py b/src/hyperloom/agents/framework/tests/test_pr_kb.py index 1ee18f4fba..c90122cb88 100644 --- a/src/hyperloom/agents/framework/tests/test_pr_kb.py +++ b/src/hyperloom/agents/framework/tests/test_pr_kb.py @@ -26,12 +26,14 @@ def test_repo_slug_examples(): assert pr_kb_slug.repo_slug("ROCm/aiter") == "rocm-aiter" assert pr_kb_slug.repo_slug("sgl-project/sglang") == "sgl-project-sglang" assert pr_kb_slug.repo_slug("https://github.com/ROCm/vllm.git") == "rocm-vllm" + assert pr_kb_slug.repo_slug("https://github.com/vllm-project/vllm.git") == "vllm-project-vllm" def test_slug_builders(monkeypatch): monkeypatch.delenv("PR_KB_SLUG_PREFIX", raising=False) assert pr_kb_slug.files_slug("ROCm/vllm", 42) == "pr-kb-files/rocm-vllm/pr/42" assert pr_kb_slug.index_slug("ROCm/vllm") == "pr-kb-index/rocm-vllm" + assert pr_kb_slug.index_slug("vllm-project/vllm") == "pr-kb-index/vllm-project-vllm" def test_slug_prefix_override(monkeypatch): diff --git a/src/hyperloom/inference_optimizer/tests/test_framework_agent_authoring.py b/src/hyperloom/inference_optimizer/tests/test_framework_agent_authoring.py index 660552ffec..02cd38bfde 100644 --- a/src/hyperloom/inference_optimizer/tests/test_framework_agent_authoring.py +++ b/src/hyperloom/inference_optimizer/tests/test_framework_agent_authoring.py @@ -1150,6 +1150,22 @@ def test_framework_agent_repo_url_origin_framework_known() -> None: ) +def test_framework_agent_repo_url_origin_framework_preserves_default_alias( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setenv( + "HYPERLOOM_VLLM_REPO_URL", + "https://github.com/vllm-project/vllm.git", + ) + assert ( + Coordinator._framework_agent_repo_url_origin_framework( + "git@github.com:vllm-project/vllm.git" + ) + == "vllm" + ) + assert Coordinator._framework_agent_repo_url_origin_framework("https://github.com/ROCm/vllm.git") == "vllm" + + def test_framework_agent_repo_url_origin_framework_unknown_or_kernel_repo() -> None: """Kernel-level pr_intel_specialist repos (aiter/triton/rccl) have no framework mapping.""" assert Coordinator._framework_agent_repo_url_origin_framework("https://github.com/ROCm/aiter.git") == "" diff --git a/src/hyperloom/inference_optimizer/tests/test_framework_agent_client_unit.py b/src/hyperloom/inference_optimizer/tests/test_framework_agent_client_unit.py index 6d4ead0a38..a86ed1a4c8 100644 --- a/src/hyperloom/inference_optimizer/tests/test_framework_agent_client_unit.py +++ b/src/hyperloom/inference_optimizer/tests/test_framework_agent_client_unit.py @@ -15,6 +15,7 @@ import pytest +from hyperloom.agents.framework import repo_map from hyperloom.orchestrator.framework import client as fac # Reference the resolver's own constant so the two never drift apart. @@ -22,11 +23,38 @@ # -- repo_url_for_framework ----------------------------------------------- -def test_repo_url_for_framework_known_and_unknown() -> None: +def test_repo_url_for_framework_known_and_unknown(monkeypatch) -> None: + monkeypatch.delenv("HYPERLOOM_VLLM_REPO_URL", raising=False) assert fac.repo_url_for_framework("sglang").endswith("sglang.git") + assert fac.repo_url_for_framework("vllm") == "https://github.com/ROCm/vllm.git" assert fac.repo_url_for_framework("nope") == "" +@pytest.mark.parametrize( + "override", + ( + "https://github.com/vllm-project/vllm.git", + "HTTPS://GITHUB.COM/vllm-project/vllm", + "git@github.com:vllm-project/vllm.git", + "vllm-project/vllm", + ), +) +def test_repo_url_for_framework_vllm_override(monkeypatch, override) -> None: + monkeypatch.setenv("HYPERLOOM_VLLM_REPO_URL", override) + assert fac.repo_url_for_framework("vllm") == "https://github.com/vllm-project/vllm.git" + assert repo_map.default_repo_url_for_framework("vllm") == "https://github.com/ROCm/vllm.git" + + +@pytest.mark.parametrize( + "override", + ("https://gitlab.com/vllm-project/vllm.git", "not-a-repo", "https://github.com/a/b/c"), +) +def test_repo_url_for_framework_rejects_invalid_override(monkeypatch, override) -> None: + monkeypatch.setenv("HYPERLOOM_VLLM_REPO_URL", override) + with pytest.raises(ValueError, match="repository override"): + fac.repo_url_for_framework("vllm") + + # -- _resolve_fa_command --------------------------------------------------- def test_resolve_fa_command_is_module_invocation(monkeypatch) -> None: """``fa`` runs as ``[python, -m, ]``, independent of $PATH.""" diff --git a/src/hyperloom/inference_optimizer/tests/test_framework_agent_discover_directed.py b/src/hyperloom/inference_optimizer/tests/test_framework_agent_discover_directed.py index f65dad5205..292d2044c7 100644 --- a/src/hyperloom/inference_optimizer/tests/test_framework_agent_discover_directed.py +++ b/src/hyperloom/inference_optimizer/tests/test_framework_agent_discover_directed.py @@ -72,8 +72,11 @@ def _call_discover(stub: _CoordinatorStub) -> bool: ) -def test_repo_urls_cover_global_allowlist_with_framework_primary(): +def test_repo_urls_cover_global_allowlist_with_framework_primary( + monkeypatch: pytest.MonkeyPatch, +): """The repo set leads with the framework's own repo, includes every PR_QUERY_REPOS entry, de-duplicated and order-preserving.""" + monkeypatch.delenv("HYPERLOOM_VLLM_REPO_URL", raising=False) stub = _CoordinatorStub(Path("/tmp")) urls = stub._framework_agent_discover_repo_urls("sglang") @@ -84,6 +87,22 @@ def test_repo_urls_cover_global_allowlist_with_framework_primary(): assert len(urls) == len(set(urls)) +def test_vllm_repo_override_replaces_rocm_fork_in_discovery( + monkeypatch: pytest.MonkeyPatch, +): + """An explicit upstream override becomes primary without querying both forks.""" + + monkeypatch.setenv( + "HYPERLOOM_VLLM_REPO_URL", + "HTTPS://GITHUB.COM/vllm-project/vllm", + ) + stub = _CoordinatorStub(Path("/tmp")) + urls = stub._framework_agent_discover_repo_urls("vllm") + + assert urls[0] == "https://github.com/vllm-project/vllm.git" + assert "https://github.com/ROCm/vllm.git" not in urls + + def test_discover_merges_candidates_across_repos( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, diff --git a/src/hyperloom/inference_optimizer/tests/test_per_domain_prompts.py b/src/hyperloom/inference_optimizer/tests/test_per_domain_prompts.py index 6a879ff928..bf906a572f 100644 --- a/src/hyperloom/inference_optimizer/tests/test_per_domain_prompts.py +++ b/src/hyperloom/inference_optimizer/tests/test_per_domain_prompts.py @@ -139,6 +139,16 @@ def test_pr_intel_specialist_mentions_cross_repo_research(): assert marker.lower() in text.lower(), f"missing {marker!r}" +def test_pr_intel_specialist_uses_vllm_repo_override(monkeypatch): + monkeypatch.setenv( + "HYPERLOOM_VLLM_REPO_URL", + "git@github.com:vllm-project/vllm.git", + ) + text = _build("pr_intel_specialist") + assert "vllm-project/vllm" in text + assert "ROCm/vllm" not in text + + def test_static_recon_specialist_mentions_reconnaissance_and_bridge_candidates(): """The static-recon focus must steer read-only source grep for disabled switches and a bridge_candidates output block.""" text = _build("static_recon_specialist") diff --git a/src/hyperloom/orchestrator/phases/framework.py b/src/hyperloom/orchestrator/phases/framework.py index 4a2b106204..0d4b56ad3a 100644 --- a/src/hyperloom/orchestrator/phases/framework.py +++ b/src/hyperloom/orchestrator/phases/framework.py @@ -2645,7 +2645,7 @@ def _framework_agent_discover_repo_urls(self, framework: str) -> list[str]: An order-preserving, deduped list of repo URLs to query. """ from ..framework import client as _fa_client - from ..specialists.domains import PR_QUERY_REPOS + from ..specialists.domains import pr_query_repos urls: list[str] = [] @@ -2663,7 +2663,7 @@ def _add(u: str) -> None: _add(_fa_client.repo_url_for_framework(framework)) # Global allowlist (owner/name -> URL). - for repo in PR_QUERY_REPOS: + for repo in pr_query_repos(): repo = str(repo or "").strip() if repo and "/" in repo: _add(f"https://github.com/{repo}.git") @@ -2696,14 +2696,24 @@ def _framework_agent_repo_url_origin_framework(repo_url: str) -> str: The lowercase framework name, or ``""`` when ``repo_url`` doesn't match any known framework's canonical repo. """ - from ..framework import client as _fa_client + from hyperloom.agents.framework.repo_map import ( + canonical_github_repo_url, + default_repo_url_for_framework, + repo_url_for_framework, + ) - normalized = (repo_url or "").strip().rstrip("/").lower() + try: + normalized = canonical_github_repo_url(repo_url).lower() + except ValueError: + return "" if not normalized: return "" for fw in ("sglang", "vllm", "atom", "xdit"): - fw_url = (_fa_client.repo_url_for_framework(fw) or "").strip().rstrip("/").lower() - if fw_url and fw_url == normalized: + urls = { + canonical_github_repo_url(repo_url_for_framework(fw)).lower(), + canonical_github_repo_url(default_repo_url_for_framework(fw)).lower(), + } + if normalized in urls - {""}: return fw return "" diff --git a/src/hyperloom/orchestrator/prompts/specialist_prompt_builder.py b/src/hyperloom/orchestrator/prompts/specialist_prompt_builder.py index f28d8cc217..6304a4dfd9 100644 --- a/src/hyperloom/orchestrator/prompts/specialist_prompt_builder.py +++ b/src/hyperloom/orchestrator/prompts/specialist_prompt_builder.py @@ -428,8 +428,8 @@ def _focus_pr_intel_specialist(inp: SpecialistPromptInputs) -> list[str]: return [ "You are a **cross-repo PR researcher**. Your role is NOT to propose", "configuration knobs — it is to surface PRs / commits / issues from", - "(ROCm/aiter, sgl-project/sglang, ROCm/vllm, triton-lang/triton,", - "ROCm/rccl) that other specialists should follow up on.", + "ROCm/aiter, triton-lang/triton, and the approved repositories listed", + "in the PR MONITOR section for other specialists to follow up on.", "", "**What to do**", "- Use ``mcp__pr_monitor__*`` + ``WebSearch`` to find recent PRs", @@ -1660,7 +1660,7 @@ def _section_pr_feed(inp: SpecialistPromptInputs) -> list[str]: Returns: list[str]: Markdown lines for the PR-query capability section. """ - from hyperloom.orchestrator.specialists.domains import PR_QUERY_REPOS + from hyperloom.orchestrator.specialists.domains import pr_query_repos rows = ["## 6. PR MONITOR", ""] if not inp.pr_monitor_available: @@ -1672,7 +1672,7 @@ def _section_pr_feed(inp: SpecialistPromptInputs) -> list[str]: "", "Repos you may query:", ] - for repo in PR_QUERY_REPOS: + for repo in pr_query_repos(): rows.append(f"- {repo}") return rows diff --git a/src/hyperloom/orchestrator/specialists/domains.py b/src/hyperloom/orchestrator/specialists/domains.py index f1c740d283..4944800aeb 100644 --- a/src/hyperloom/orchestrator/specialists/domains.py +++ b/src/hyperloom/orchestrator/specialists/domains.py @@ -19,8 +19,14 @@ from __future__ import annotations +import os from dataclasses import dataclass +from hyperloom.agents.framework.repo_map import ( + VLLM_REPO_URL_ENV, + github_repo_name, +) + @dataclass(frozen=True) class SpecialistDomain: @@ -63,6 +69,15 @@ class SpecialistDomain: ) +def pr_query_repos() -> tuple[str, ...]: + """Return the effective PR-query allowlist with any vLLM override.""" + + override = github_repo_name(os.environ.get(VLLM_REPO_URL_ENV, "")) + if not override: + return PR_QUERY_REPOS + return tuple(override if repo == "ROCm/vllm" else repo for repo in PR_QUERY_REPOS) + + # Canonical catalogue; PolicyGate R2's `specialist_unknown_domain` rule reads this set. SPECIALIST_DOMAINS: tuple[SpecialistDomain, ...] = ( SpecialistDomain( @@ -368,4 +383,5 @@ def get_domain(key: str) -> SpecialistDomain | None: "domain_for_tag", "get_domain", "normalize_dispatch_tags", + "pr_query_repos", ]