mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-21 05:11:26 +00:00
refactor(inventory): extract shared ConfigContext + build_models_payload
Three call-sites in the codebase each duplicated the same config-slice
+ list_authenticated_providers + post-processing pattern:
- hermes_cli/web_server.py /api/model/options
- tui_gateway/server.py model.options JSON-RPC
- tui_gateway/server.py model.save_key JSON-RPC
This consolidates them onto hermes_cli/inventory.py:
load_picker_context() -> ConfigContext
Replaces the 17-LOC config-slice (model.{default,name,provider,
base_url}, providers:, custom_providers:) every consumer did
inline.
ConfigContext.with_overrides(*, current_provider=, current_model=,
current_base_url=) -> ConfigContext
Truthy-only overlay for TUI agent-session state on top of disk
config. Empty getattr(agent, ...) attrs MUST NOT clobber disk.
build_models_payload(ctx, *, include_unconfigured, picker_hints,
canonical_order, max_models) -> dict
Single payload builder. Delegates curation to
list_authenticated_providers (does not call provider_model_ids
per row \u2014 that pulls non-agentic models). picker_hints +
canonical_order produce the TUI ModelPickerDialog shape;
defaults match the dashboard's existing /api/model/options
contract.
Two latent bugs fixed by consolidation:
1. The dashboard read cfg.get('custom_providers') directly, missing
the v12+ keyed providers: form. Now both surfaces go through
get_compatible_custom_providers().
2. The TUI's canonical-merge keyed on is_user_defined to decide order.
Section 3 of list_authenticated_providers sets is_user_defined=True
on rows from the providers: config dict even when the slug is
canonical \u2014 that silently demoted them to the picker tail.
_reorder_canonical now keys on slug membership instead.
Stats: +666 / -145 (net +521). Module 240 LOC; 18 behavior tests.
This PR replaces the rejected #23369 (which bundled the consolidation
with new scriptable CLI surfaces \u2014 hermes models list/status, hermes
providers list \u2014 and a JSON contract that have no external user
demand). Just the refactor; the CLI surface is deferred to a separate
PR gated on actual demand.
Refs #23359.
This commit is contained in:
parent
4ceab16893
commit
efc32ab639
4 changed files with 666 additions and 145 deletions
|
|
@ -994,39 +994,9 @@ def get_model_options():
|
|||
can share the same types.
|
||||
"""
|
||||
try:
|
||||
from hermes_cli.model_switch import list_authenticated_providers
|
||||
from hermes_cli.inventory import build_models_payload, load_picker_context
|
||||
|
||||
cfg = load_config()
|
||||
model_cfg = cfg.get("model", {})
|
||||
if isinstance(model_cfg, dict):
|
||||
current_model = model_cfg.get("default", model_cfg.get("name", "")) or ""
|
||||
current_provider = model_cfg.get("provider", "") or ""
|
||||
current_base_url = model_cfg.get("base_url", "") or ""
|
||||
else:
|
||||
current_model = str(model_cfg) if model_cfg else ""
|
||||
current_provider = ""
|
||||
current_base_url = ""
|
||||
|
||||
user_providers = cfg.get("providers") if isinstance(cfg.get("providers"), dict) else {}
|
||||
custom_providers = (
|
||||
cfg.get("custom_providers")
|
||||
if isinstance(cfg.get("custom_providers"), list)
|
||||
else []
|
||||
)
|
||||
|
||||
providers = list_authenticated_providers(
|
||||
current_provider=current_provider,
|
||||
current_base_url=current_base_url,
|
||||
current_model=current_model,
|
||||
user_providers=user_providers,
|
||||
custom_providers=custom_providers,
|
||||
max_models=50,
|
||||
)
|
||||
return {
|
||||
"providers": providers,
|
||||
"model": current_model,
|
||||
"provider": current_provider,
|
||||
}
|
||||
return build_models_payload(load_picker_context(), max_models=50)
|
||||
except Exception:
|
||||
_log.exception("GET /api/model/options failed")
|
||||
raise HTTPException(status_code=500, detail="Failed to list model options")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue