From b7505a1602bb0fbf686a9cd8cd88974caa3497d3 Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Thu, 1 Oct 2026 19:41:57 +0530 Subject: [PATCH] fix(cron): name a malformed base_url as invalid; read custom providers via the public view A base_url that urlparse rejects (e.g. an unclosed IPv6 bracket) was refused with the stored-key/origin explanation, which tells the user to configure the endpoint as a custom provider - advice that cannot help a URL that does not parse. It now says "It is not a valid URL." while keeping the shared "not allowed" refusal wording; the existing test pins it. The configured-origin list read custom providers through the private agent.credential_pool._iter_custom_providers, which reloads config and only wraps hermes_cli.config.get_compatible_custom_providers. Every entry that view returns is a dict with a non-empty name and base_url, so the name filter in the private iterator never drops one; calling rp.get_compatible_custom_providers on the config already loaded here gives the same base_urls without a second config load or a private import. --- tests/tools/test_cronjob_tools.py | 2 +- tools/cronjob_job_args.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/tools/test_cronjob_tools.py b/tests/tools/test_cronjob_tools.py index 57a76452d1..02b65644f4 100644 --- a/tests/tools/test_cronjob_tools.py +++ b/tests/tools/test_cronjob_tools.py @@ -710,7 +710,7 @@ class TestValidateCronBaseUrl: assert err and "not allowed" in err, bu # A URL urlparse rejects is refused, not raised out of create/update. err = self._v("custom", "http://[::1/v1") - assert err and "not allowed" in err + assert err and "not allowed" in err and "not a valid URL" in err assert self._v("custom", configured) is None keyless = "http://192.0.2.10:8080/v1" assert attached(keyless) != stored and self._v("custom", keyless) is None diff --git a/tools/cronjob_job_args.py b/tools/cronjob_job_args.py index 99826cffd4..9c02e0e891 100644 --- a/tools/cronjob_job_args.py +++ b/tools/cronjob_job_args.py @@ -330,7 +330,6 @@ def _custom_stored_key_error(bu: str) -> Optional[str]: the host-gated env keys by HOSTNAME, so a base_url that would receive one must be an origin the operator or the provider registry names; pool and ``model.key_env`` keys already match their configured URL exactly.""" - from agent.credential_pool import _iter_custom_providers from agent.secret_scope import get_secret_str from hermes_cli import runtime_provider as rp from hermes_cli.auth import PROVIDER_REGISTRY @@ -344,17 +343,18 @@ def _custom_stored_key_error(bu: str) -> Optional[str]: try: # a URL urlparse rejects (unclosed IPv6 bracket) would raise in the key lookup below base_url_origin(bu) except ValueError: - return _base_url_refused(bu, "custom", custom_why) + return _base_url_refused(bu, "custom", "It is not a valid URL.") if not any(rp.has_usable_secret(key) for key in rp._host_gated_env_key_candidates(bu, ollama=True)): return None # The RAW configured model.base_url: _get_model_config() may network-probe a local model. - model_cfg = rp.load_config().get("model") + cfg = rp.load_config() + model_cfg = cfg.get("model") configured = [ model_cfg.get("base_url") if isinstance(model_cfg, dict) else None, get_secret_str("OPENAI_BASE_URL", ""), OPENROUTER_BASE_URL, # PROVIDER_REGISTRY already carries the direct OpenAI origin (openai-api). *(getattr(p, "inference_base_url", "") for p in PROVIDER_REGISTRY.values()), - *(entry.get("base_url") for _, entry in _iter_custom_providers()), + *(entry.get("base_url") for entry in rp.get_compatible_custom_providers(cfg)), ] if any(_same_origin(bu, str(url)) for url in configured if url): return None