fix(#4728): persist provider-only default-model changes end to end
This commit is contained in:
1 parent
69d202b94a
commit
bede035a5e
5 files changed
+27
-7
No files matched your search
+4
-3
@@ -3555,7 +3555,7 @@ def _apply_advanced_model_options(model_cfg: dict, advanced: dict | None) -> Non
|
||||
model_cfg["api_key"] = api_key
|
||||
|
||||
|
||||
def set_hermes_default_model(model_id: str, advanced: dict | None = None) -> dict:
|
||||
def set_hermes_default_model(model_id: str, provider: str | None = None, advanced: dict | None = None) -> dict:
|
||||
"""Persist the Hermes default model in config.yaml and reload runtime config."""
|
||||
selected_model = str(model_id or "").strip()
|
||||
if not selected_model:
|
||||
@@ -3572,6 +3572,7 @@ def set_hermes_default_model(model_id: str, advanced: dict | None = None) -> dic
|
||||
model_cfg = {}
|
||||
|
||||
previous_provider = str(model_cfg.get("provider") or "").strip()
|
||||
requested_provider = str(provider or "").strip()
|
||||
resolved_model, resolved_provider, resolved_base_url = resolve_model_provider(
|
||||
selected_model
|
||||
)
|
||||
@@ -3585,7 +3586,7 @@ def set_hermes_default_model(model_id: str, advanced: dict | None = None) -> dic
|
||||
# CLI-shaped bare form via `_applyModelToDropdown()`'s normalising
|
||||
# matcher — see `static/panels.js` (#895).
|
||||
persisted_model = str(resolved_model or selected_model).strip()
|
||||
persisted_provider = str(resolved_provider or previous_provider or "").strip()
|
||||
persisted_provider = str(requested_provider or resolved_provider or previous_provider or "").strip()
|
||||
# Never persist the bogus ``local`` value — see #1384. The auto-detect
|
||||
# block in ``_build_available_models_uncached`` was rewriting unknown
|
||||
# loopback hosts to ``provider: "local"``, which is not registered and
|
||||
@@ -3617,7 +3618,7 @@ def set_hermes_default_model(model_id: str, advanced: dict | None = None) -> dic
|
||||
# it triggers a live provider fetch (up to 8s) that blocks the HTTP response
|
||||
# to the browser, causing a visible freeze on every Settings save (#895).
|
||||
invalidate_models_cache()
|
||||
return {"ok": True, "model": persisted_model}
|
||||
return {"ok": True, "model": persisted_model, "provider": persisted_provider or None}
|
||||
|
||||
|
||||
# ── Auxiliary model configuration ──────────────────────────────────────────
|
||||
|
||||
+3
-2
@@ -10943,7 +10943,8 @@ def handle_post(handler, parsed) -> bool:
|
||||
if parsed.path == "/api/default-model":
|
||||
try:
|
||||
advanced = body.get("advanced") if isinstance(body, dict) else None
|
||||
return j(handler, set_hermes_default_model(body.get("model"), advanced=advanced))
|
||||
provider = body.get("provider") if isinstance(body, dict) else None
|
||||
return j(handler, set_hermes_default_model(body.get("model"), provider=provider, advanced=advanced))
|
||||
except ValueError as e:
|
||||
return bad(handler, str(e))
|
||||
except RuntimeError as e:
|
||||
@@ -10964,7 +10965,7 @@ def handle_post(handler, parsed) -> bool:
|
||||
return bad(handler, str(exc), status=400)
|
||||
if scope == "main":
|
||||
try:
|
||||
return j(handler, set_hermes_default_model(model, advanced=advanced))
|
||||
return j(handler, set_hermes_default_model(model, provider=provider, advanced=advanced))
|
||||
except ValueError as exc:
|
||||
return bad(handler, str(exc), status=400)
|
||||
return bad(handler, f"unknown scope: {scope}", status=400)
|
||||
|
||||
+2
-2
@@ -9795,7 +9795,7 @@ async function saveSettings(andClose){
|
||||
const saved=await api('/api/settings',{method:'POST',body:JSON.stringify(payload)});
|
||||
if(modelChanged && model){
|
||||
try{
|
||||
await api('/api/default-model',{method:'POST',body:JSON.stringify({model})});
|
||||
await api('/api/default-model',{method:'POST',body:JSON.stringify({model,provider:modelState.model_provider||null})});
|
||||
body.default_model=model;
|
||||
body.default_model_provider=(modelState&&modelState.model===model)?(modelState.model_provider||null):null;
|
||||
}catch(_modelErr){
|
||||
@@ -9825,7 +9825,7 @@ async function saveSettings(andClose){
|
||||
const saved=await api('/api/settings',{method:'POST',body:JSON.stringify(body)});
|
||||
if(modelChanged && model){
|
||||
try{
|
||||
await api('/api/default-model',{method:'POST',body:JSON.stringify({model})});
|
||||
await api('/api/default-model',{method:'POST',body:JSON.stringify({model,provider:modelState.model_provider||null})});
|
||||
body.default_model=model;
|
||||
body.default_model_provider=(modelState&&modelState.model===model)?(modelState.model_provider||null):null;
|
||||
}catch(_modelErr){
|
||||
|
||||
@@ -474,6 +474,23 @@ class TestAuxiliaryModelsBackend:
|
||||
assert "reasoning_effort: none" in text
|
||||
assert "DUMMY_KEY_DO_NOT_PRINT" in text
|
||||
|
||||
def test_set_hermes_default_model_persists_explicit_provider_override(self, monkeypatch, tmp_path):
|
||||
from api import config
|
||||
|
||||
config_path = tmp_path / "config.yaml"
|
||||
config_path.write_text("model:\n provider: openai\n default: gpt-5.5\n", encoding="utf-8")
|
||||
monkeypatch.setattr(config, "_get_config_path", lambda: config_path)
|
||||
monkeypatch.setattr(config, "reload_config", lambda: None)
|
||||
monkeypatch.setattr(config, "invalidate_models_cache", lambda: None)
|
||||
monkeypatch.setattr(config, "resolve_model_provider", lambda model: (model, "", None))
|
||||
|
||||
result = config.set_hermes_default_model("gpt-5.5", provider="anthropic")
|
||||
|
||||
assert result["ok"] is True
|
||||
assert result["provider"] == "anthropic"
|
||||
text = config_path.read_text(encoding="utf-8")
|
||||
assert "provider: anthropic" in text
|
||||
|
||||
def test_set_auxiliary_model_persists_advanced_options(self, monkeypatch, tmp_path):
|
||||
"""Gear-modal payload should persist supported per-slot options."""
|
||||
from api import config
|
||||
|
||||
@@ -162,6 +162,7 @@ def test_save_settings_syncs_default_model_provider_with_saved_model():
|
||||
autosave_block = panels_js[panels_js.index("const pwField=$('settingsPassword');"):panels_js.index("if(!pwDirty&&!modelDirty){", panels_js.index("const pwField=$('settingsPassword');")) + 24]
|
||||
|
||||
assert "_captureModelDropdownSelection($('settingsModel'))" in save_block
|
||||
assert "JSON.stringify({model,provider:modelState.model_provider||null})" in save_block
|
||||
assert "body.default_model_provider=(modelState&&modelState.model===model)?(modelState.model_provider||null):null;" in save_block
|
||||
assert "const modelChanged=(model||'')!==(_settingsHermesDefaultModelOnOpen||'')||((modelState.model_provider||null)!==(_settingsHermesDefaultModelProviderOnOpen||null));" in save_block
|
||||
assert "if(Object.prototype.hasOwnProperty.call(body,'default_model_provider')) window._activeProvider=body.default_model_provider||null;" in apply_saved_block
|
||||
|
||||
Reference in new issue
Block a user