fix(cron): restore reasoning_effort on cronjob() for the CLI lane — model dispatch still drops it
The CLI (hermes cron create/edit) routes through cronjob(); removing the parameter outright broke that lane (CI slices 6/9). The parameter is back on the function, but CRONJOB_SCHEMA and the registry handler still omit it — same pattern as the intentional model/provider/base_url omission. New test proves a hallucinated reasoning_effort arg through the model dispatch is dropped.
This commit is contained in:
@@ -191,13 +191,42 @@ class TestCronjobToolReasoningEffort:
|
||||
listed = json.loads(cronjob(action="list"))["jobs"][0]
|
||||
assert "reasoning_effort" not in listed
|
||||
|
||||
def _tool_handler(self):
|
||||
import tools.cronjob_tools as mod
|
||||
|
||||
return mod.registry._tools["cronjob"].handler
|
||||
|
||||
def test_schema_does_not_expose_reasoning_effort(self):
|
||||
"""Policy pin: the model-facing tool schema must NOT offer the
|
||||
"""Policy pin: the model-facing surface must NOT offer the
|
||||
reasoning_effort knob. Models never choose model config; the CLI is
|
||||
the only mutation surface for this field."""
|
||||
the only mutation surface for this field. The cronjob() function
|
||||
keeps the parameter for the CLI lane (hermes_cli/cron.py), but the
|
||||
tool schema and the registry dispatch drop it — same pattern as
|
||||
model/provider/base_url."""
|
||||
import inspect
|
||||
|
||||
from tools.cronjob_tools import CRONJOB_SCHEMA, cronjob
|
||||
import tools.cronjob_tools as mod
|
||||
|
||||
assert "reasoning_effort" not in CRONJOB_SCHEMA["parameters"]["properties"]
|
||||
assert "reasoning_effort" not in inspect.signature(cronjob).parameters
|
||||
assert "reasoning_effort" not in mod.CRONJOB_SCHEMA["parameters"]["properties"]
|
||||
# The registry handler lambda must not forward the agent's args to
|
||||
# the parameter (mirrors the intentional model/provider omission).
|
||||
source = inspect.getsource(self._tool_handler())
|
||||
assert 'args.get("reasoning_effort")' not in source
|
||||
|
||||
def test_tool_dispatch_drops_reasoning_effort_arg(self, tmp_cron_dir):
|
||||
"""Even if a model hallucinates the argument, dispatch ignores it:
|
||||
the created job must carry NO pin."""
|
||||
import json
|
||||
|
||||
out = json.loads(
|
||||
self._tool_handler()(
|
||||
{
|
||||
"action": "create",
|
||||
"prompt": "daily digest",
|
||||
"schedule": "every 1h",
|
||||
"reasoning_effort": "max",
|
||||
}
|
||||
)
|
||||
)
|
||||
assert out["success"] is True
|
||||
assert load_jobs()[0].get("reasoning_effort") is None
|
||||
|
||||
@@ -1213,6 +1213,7 @@ def cronjob(
|
||||
attach_to_session: Optional[bool] = None,
|
||||
monitor_script: Optional[str] = None,
|
||||
monitor_url: Optional[str] = None,
|
||||
reasoning_effort: Optional[str] = None,
|
||||
task_id: str = None,
|
||||
session_id: Optional[str] = None,
|
||||
) -> str:
|
||||
@@ -1313,6 +1314,12 @@ def cronjob(
|
||||
attach_to_session=attach_to_session,
|
||||
monitor_script=_normalize_optional_job_value(monitor_script),
|
||||
monitor_url=_normalize_optional_job_value(monitor_url),
|
||||
# reasoning_effort reaches here from the CLI
|
||||
# (hermes cron create --reasoning-effort) ONLY — it is
|
||||
# deliberately absent from CRONJOB_SCHEMA and the model
|
||||
# dispatch below: models do not make model-config
|
||||
# decisions (standing policy).
|
||||
reasoning_effort=reasoning_effort,
|
||||
)
|
||||
except CronSchedulerRegistrationError as exc:
|
||||
_partial = exc.to_dict()
|
||||
@@ -1495,6 +1502,10 @@ def cronjob(
|
||||
updates["provider"] = _normalize_optional_job_value(provider)
|
||||
if base_url is not None:
|
||||
updates["base_url"] = _normalize_optional_job_value(base_url, strip_trailing_slash=True)
|
||||
if reasoning_effort is not None:
|
||||
# CLI-only lane (see create above): update_job validates
|
||||
# against the canonical grammar; empty string clears the pin.
|
||||
updates["reasoning_effort"] = reasoning_effort
|
||||
# Re-validate the EFFECTIVE provider/base_url on EVERY update, not
|
||||
# only when this update supplies provider/base_url. A job persisted
|
||||
# before this guard (or written directly to the jobs store) may
|
||||
|
||||
Reference in New Issue
Block a user