fix(agent): a task with its own URL re-probes when that URL's pin changes

The route identity read a provider entry's context pin only for a task that names the entry. A task with `provider: custom` and its own `base_url` returned early, but the probe still reads the pin of the entry at that URL, so lowering only that pin (900K to 80K) left a warm agent's trigger on the old window. The identity now carries the pin for the route's own URL too.

Reported-by: greptile-apps[bot]
This commit is contained in:
yoniebans authored and jonny committed 2026-11-05 12:09:34 +01:00
1 parent 129e86cd1d
commit 8e7cf55eb6
2 files changed
+37 -8

No files matched your search

+13 -8
View File
@@ -24,7 +24,8 @@ def _mark_checked(agent: Any, route: tuple) -> None:
def compression_route_identity() -> tuple:
"""The configured compression route a probe measures: the task's provider, model, URL and context
length, plus the URL of a ``providers:`` / ``custom_providers:`` entry the task names. A config this
length, the URL of a ``providers:`` / ``custom_providers:`` entry the task names, and the context pin
a provider entry sets for the compression model at the route's URL. A config this
cannot read yields ``("unreadable",)``: the main request carries on and the probe reports the problem."""
try:
return _route_identity()
@@ -38,15 +39,19 @@ def _route_identity() -> tuple:
cfg = _get_auxiliary_task_config("compression")
route = tuple(str(cfg.get(k) or "") for k in ("provider", "model", "base_url", "context_length"))
provider = route[0].strip()
if not provider or provider in ("auto", "main", "custom") or route[2]:
return route
from hermes_cli.config import get_custom_provider_context_length
from hermes_cli.runtime_provider_custom import _get_named_custom_provider
entry = _get_named_custom_provider(provider, resolve_credentials=False) or {}
url, model = str(entry.get("base_url") or ""), route[1] or str(entry.get("model") or "")
# The context pin the probe will read for this model at this URL (per-model, else entry-level).
if route[2]:
url, model, named = route[2], route[1], ()
elif not provider or provider in ("auto", "main", "custom"):
return route
else:
from hermes_cli.runtime_provider_custom import _get_named_custom_provider
entry = _get_named_custom_provider(provider, resolve_credentials=False) or {}
url, model = str(entry.get("base_url") or ""), route[1] or str(entry.get("model") or "")
named = (url, str(entry.get("model") or ""))
# The context pin the probe reads for this model at this URL (a matching entry's per-model, else entry-level).
pin = get_custom_provider_context_length(model=model, base_url=url) if url and model else None
return route + (url, str(entry.get("model") or ""), str(pin or ""))
return route + named + (str(pin or ""),)
def _drop_stale_ceiling(agent: Any) -> None:
@@ -710,6 +710,30 @@ def test_a_changed_provider_context_pin_reprobes_a_warm_agent(monkeypatch, tmp_p
assert agent.context_compressor.threshold_tokens == 80_000
def test_a_changed_provider_pin_reprobes_a_task_that_sets_its_own_url(monkeypatch, tmp_path):
"""``provider: custom`` with the task's own ``base_url``: the probe still reads the pin of the
provider entry at that URL, so lowering only that pin (900K to 80K) re-probes a warm agent."""
import json
from agent.conversation_compression_feasibility import ensure_compression_feasibility_checked
home = tmp_path / "home"
home.mkdir()
monkeypatch.setenv("HERMES_HOME", str(home))
url = "http://gateway.invalid/v1"
task = {"provider": "custom", "model": "small", "base_url": url}
entry = {"name": "work-gateway", "base_url": url, "models": {"small": {"context_length": 900_000}}}
(home / "config.yaml").write_text(json.dumps({"auxiliary": {"compression": task}, "custom_providers": [entry]}))
agent = _warm_agent_on(home, [entry])
(home / "config.yaml").write_text(json.dumps({"auxiliary": {"compression": task}, "custom_providers": [entry]}))
client = MagicMock(base_url=url, api_key="test-key")
with patch("agent.auxiliary_client.get_text_auxiliary_client", return_value=(client, "small")):
ensure_compression_feasibility_checked(agent, 200_000)
assert agent.context_compressor.threshold_tokens == 750_000
entry["models"]["small"]["context_length"] = 80_000
(home / "config.yaml").write_text(json.dumps({"auxiliary": {"compression": task}, "custom_providers": [entry]}))
ensure_compression_feasibility_checked(agent, 200_000)
assert agent.context_compressor.threshold_tokens == 80_000
def test_a_route_edited_during_the_probe_is_probed_again(monkeypatch, tmp_path):
"""The latch records the route the probe measured: an edit that lands while the probe runs is
probed on the next request instead of being labelled with the earlier measurement."""