fix(auxiliary): route direct-create aux callers through call_llm (#65029)

* fix(auxiliary): route direct-create aux callers through call_llm (#35566)

Five callers (kanban_decompose, kanban_specify, profile_describer, and
goals.py's judge + draft-contract) built raw clients via
get_text_auxiliary_client() and passed extra_body=get_auxiliary_extra_body()
— which only returns Nous portal tags and ignores
auxiliary.<task>.extra_body from config.yaml entirely. That was the
remaining half of #35566 after the call_llm path was fixed.

Routing them through call_llm(task=...) gives each caller the full
auxiliary contract for free: task extra_body, the reasoning_effort
shorthand, transient retries, provider-profile projection, and fallback
chains. goal_judge gains a DEFAULT_CONFIG block (it had none — its
provider/model overrides silently didn't exist as documented keys).

get_auxiliary_extra_body() now has zero non-test callers; kept for
plugin back-compat.

Fixes #35566.

* test: migrate kanban dashboard + CLI specify mocks to call_llm

Two more consumers of specify_task mocked the old
get_text_auxiliary_client symbol (missed in the first sibling sweep —
they live outside tests/hermes_cli's kanban files): the dashboard
plugin's /specify endpoint tests and the /kanban slash-command E2E.
Same migration as the rest: mock call_llm at the source, no-provider
now surfaces via the LLM-error branch.
This commit is contained in:
Teknium 2026-07-15 07:39:17 -07:00 committed by GitHub
parent 306e2d2318
commit 7c954969b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 141 additions and 241 deletions

View file

@ -2182,13 +2182,10 @@ def _patch_specifier_response(monkeypatch, *, content, model="test-model"):
resp = MagicMock()
resp.choices = [MagicMock()]
resp.choices[0].message.content = content
fake_client = MagicMock()
fake_client.chat.completions.create = MagicMock(return_value=resp)
monkeypatch.setattr(
"agent.auxiliary_client.get_text_auxiliary_client",
lambda *a, **kw: (fake_client, model),
)
return fake_client
# specify_task routes through call_llm now (#35566) — mock it directly.
fake_call = MagicMock(return_value=resp)
monkeypatch.setattr("agent.auxiliary_client.call_llm", fake_call)
return fake_call
def test_specify_happy_path(client, monkeypatch):
@ -2250,11 +2247,11 @@ def test_specify_no_aux_client_surfaces_reason(client, monkeypatch):
json={"title": "rough", "triage": True},
).json()["task"]
# Simulate "no auxiliary client configured".
monkeypatch.setattr(
"agent.auxiliary_client.get_text_auxiliary_client",
lambda *a, **kw: (None, ""),
)
# Simulate "no auxiliary client configured" — call_llm raises when
# no provider resolves (#35566 routing).
def _no_provider(**kwargs):
raise RuntimeError("No LLM provider configured")
monkeypatch.setattr("agent.auxiliary_client.call_llm", _no_provider)
r = client.post(
f"/api/plugins/kanban/tasks/{t['id']}/specify",
@ -2263,7 +2260,8 @@ def test_specify_no_aux_client_surfaces_reason(client, monkeypatch):
assert r.status_code == 200
body = r.json()
assert body["ok"] is False
assert "auxiliary client" in body["reason"]
# call_llm's no-provider RuntimeError surfaces via the LLM-error branch.
assert "LLM error" in body["reason"]
# Task must stay in triage — nothing was touched.
detail = client.get(f"/api/plugins/kanban/tasks/{t['id']}").json()["task"]