feat(hermes): first-class Omnigent model control for the hermes harness - #1971
feat(hermes): first-class Omnigent model control for the hermes harness#1971appletechie wants to merge 2 commits into
Conversation
Demo — hermes model override, end-to-end (
|
|
⏰ Reviewer SLA — this PR has been awaiting review from @dhruv0811 for more than 5 working days. Adding @TomeHirata as a second reviewer. |
|
/review |
|
2891fb9 to
9b78af7
Compare
|
Sorry for the slow turnaround on the review note — confirming both points now, verified directly against an installed Hermes CLI (v0.19.0, 1. 2. Worth noting this is v0.19.0 while the original demo was v0.18.0, so the flag survived a minor version bump rather than being a point-in-time observation. Rebasing onto current |
… harness
Register the `hermes` CLI-subprocess harness in `model_env_keys`
(`HARNESS_HERMES_MODEL`) and add `_build_hermes_spawn_env` so `args.model` /
`executor.model` — and a per-session `/model` override — actually reach the
Hermes CLI as `hermes chat -m <model>`. Before this, `_build_spawn_env_from_spec`
returned `None` for hermes and the `sys_session_send` dispatch gate rejected any
model ("no model-override plumbing"), so a model chosen for a hermes agent was
silently dropped. The executor already consumed `HARNESS_HERMES_MODEL` and
threaded `-m`; the only missing link was the registration + spawn-env builder.
hermes-native (the resident TUI) is a native harness, so — like cursor-native —
the override reaches the CLI as a top-level `hermes -m <model>` argv at terminal
launch (new `_hermes_launch_args_with_model` helper, guarded against a
user-pinned `-m`/`--model` in passthrough args), not via an env var. It is
therefore intentionally kept out of `model_env_keys`.
Also fix `_read_model_from_hermes_config`: real Hermes configs store `model` as
a `{default, provider}` mapping, so the old `isinstance(str)` check always
returned None and the web usage/model readout was blank; now surface
`model.default`.
Mechanism verified end-to-end against the installed hermes CLI:
`hermes chat -v -m gpt-5.4` reports `AI Agent initialized with model: gpt-5.4`
vs the `gpt-5.5` default, and `HARNESS_HERMES_MODEL=gpt-5.4` drives the harness
wrap -> `HermesExecutor(model=gpt-5.4)` -> `hermes chat ... -m gpt-5.4`.
Tests: spawn-env threading + override application, model_env_keys/override-gate
registration, native `-m` launch guard, and the dict-shaped model reader. Full
local gate green (442 passed): harness readiness/plugins/capabilities invariants,
run-harness-without-agent e2e, runtime/harnesses, model_override, and all hermes
suites; ruff check + format clean.
Co-authored-by: omnigent <noreply@omnigent.ai>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: apeltekci <andrew@peltekci.com>
…itch) Terminal-rendered PNG of two REAL headless `hermes chat -q "say hi" -Q -v` turns captured under a PTY against Hermes Agent CLI v0.18.0 (provider openai-codex). Default run initializes on the ~/.hermes/config.yaml default gpt-5.5; adding `-m gpt-5.4` flips the AI-agent init line, the conversation turn, and API call #1 to gpt-5.4 — showing Omnigent's model override reaching the hermes CLI. No credentials in the asset. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: apeltekci <andrew@peltekci.com>
9b78af7 to
6283349
Compare
|
Rebased onto current One thing worth flagging, since the diff moved files and that isn't obvious from a rebase: The native-TUI half had to be re-ported. Two incidental cleanups the rebase surfaced:
Re-verified after the rebase: Wider sweep ( |

Summary
Gives Omnigent first-class model control over the
hermesharness. Before this, a model chosen for a hermes agent (args.model,executor.model, or a per-session/modeloverride) was silently dropped:_build_spawn_env_from_specreturnedNonefor hermes and thesys_session_senddispatch gate rejected any model ("no model-override plumbing"). TheHermesExecutoralready threadedHARNESS_HERMES_MODEL→hermes chat -m <model>; the only missing link was Omnigent feeding a model to it.What changed
hermes(CLI-subprocess, OWN_AUTH): registeredhermes → HARNESS_HERMES_MODELinmodel_env_keys(harness_plugins.py) — the single source that drives the SDK-override set, the env-key map, and the dispatch gate. Added_build_hermes_spawn_env(runtime/workflow.py, mirroring the kimi sibling: model + cwd + os_env only, no provider/profile surface since it's OWN_AUTH) and wired thehermesbranch into_build_spawn_env_from_spec.hermes-native(resident TUI, native harness): threads the override as a top-levelhermes -m <model>argv at terminal launch (runner/app.py_hermes_launch_args_with_model), guarded against a user-pinned-m/--model/--model=in passthrough args. Intentionally kept out ofmodel_env_keys(like cursor-native)._read_model_from_hermes_config(hermes_native_forwarder.py) assumedmodelwas a string, but real Hermes configs store{default, provider}— so the web model/usage readout was blank. Now surfacesmodel.default, preserves the legacy string shape, and stays defensive.Verification
hermes chat -v -m gpt-5.4→ "AI Agent initialized with model: gpt-5.4" vs thegpt-5.5config default;HARNESS_HERMES_MODEL=gpt-5.4drivesHermesExecutor(model=gpt-5.4)→hermes chat … -m gpt-5.4.model_env_keys/override-gate registration, native-mlaunch guard, dict-shaped config reader. Full local gate green (442 passed); harness-enumeration invariant (test_configured_harness_map_covers_all_spellings) included and passing.Demo
Real
gpt-5.5 → gpt-5.4override across the init line, conversation-turn log, and the actual API call (Hermes CLI v0.18.0). See the PR comment for the transcript.