diff --git a/agent/curator.py b/agent/curator.py index c13a36ecbbd3..df5c5c99fb06 100644 --- a/agent/curator.py +++ b/agent/curator.py @@ -1850,6 +1850,8 @@ def _run_llm_review(prompt: str) -> Dict[str, Any]: _base_url = None _api_mode = None _resolved_provider = None + _credential_pool = None + _request_overrides = None _model_name = "" try: from hermes_cli.config import load_config @@ -1867,6 +1869,8 @@ def _run_llm_review(prompt: str) -> Dict[str, Any]: _base_url = _rp.get("base_url") _api_mode = _rp.get("api_mode") _resolved_provider = _rp.get("provider") or _provider + _credential_pool = _rp.get("credential_pool") + _request_overrides = _rp.get("request_overrides") except Exception as e: logger.debug("Curator provider resolution failed: %s", e, exc_info=True) @@ -1881,6 +1885,8 @@ def _run_llm_review(prompt: str) -> Dict[str, Any]: api_key=_api_key, base_url=_base_url, api_mode=_api_mode, + credential_pool=_credential_pool, + request_overrides=_request_overrides, # Umbrella-building over a large skill collection is worth a # high iteration ceiling — the pass typically takes 50-100 # API calls against hundreds of candidate skills. The diff --git a/tests/agent/test_curator.py b/tests/agent/test_curator.py index 7e67246dbb38..75688b6bdea1 100644 --- a/tests/agent/test_curator.py +++ b/tests/agent/test_curator.py @@ -1273,3 +1273,54 @@ def run_conversation(self, user_message=None, **kwargs): "'background_review' — the skill_manage background-review write " "guard would not fire (GH-47688 regression)" ) + + +def test_review_fork_forwards_runtime_pool_and_overrides(curator_env, monkeypatch): + """Curator must pass credential_pool + request_overrides from resolve_runtime_provider.""" + curator = curator_env["curator"] + import importlib + importlib.reload(curator) + + fake_pool = object() + fake_overrides = {"extra_body": {"store": False}} + captured = {} + + def _fake_resolve_runtime_provider(**kwargs): + return { + "provider": "custom", + "api_key": "pool-token", + "base_url": "https://hyper.charm.land/v1", + "api_mode": "chat_completions", + "credential_pool": fake_pool, + "request_overrides": fake_overrides, + } + + class _StubAgent: + def __init__(self, *args, **kwargs): + captured["kwargs"] = kwargs + self._memory_write_origin = "assistant_tool" + self._memory_nudge_interval = 0 + self._skill_nudge_interval = 0 + self._session_messages = [] + + def run_conversation(self, user_message=None, **kwargs): + return {"final_response": "ok"} + + def close(self): + pass + + monkeypatch.setattr( + "hermes_cli.config.load_config", + lambda: {"model": {"provider": "custom:hyper-charm", "default": "glm-5.2"}}, + ) + monkeypatch.setattr( + "hermes_cli.runtime_provider.resolve_runtime_provider", + _fake_resolve_runtime_provider, + ) + monkeypatch.setattr("run_agent.AIAgent", _StubAgent) + + meta = curator._run_llm_review("review prompt") + + assert meta.get("error") is None, meta.get("error") + assert captured["kwargs"]["credential_pool"] is fake_pool + assert captured["kwargs"]["request_overrides"] == fake_overrides